]> code.delx.au - gnu-emacs/blobdiff - lisp/diff-mode.el
(custom-face-attributes): Handle mapping `nil' and `unspecified' to
[gnu-emacs] / lisp / diff-mode.el
index 48fd92b764f67a5c127a37396887af99bb5e78c1..8d836894f5d9d90f2f53e0f93527cca614af5bf9 100644 (file)
@@ -4,7 +4,7 @@
 
 ;; Author: Stefan Monnier <monnier@cs.yale.edu>
 ;; Keywords: patch diff
-;; Revision: $Id: diff-mode.el,v 1.29 2000/10/15 04:49:55 monnier Exp $
+;; Revision: $Id: diff-mode.el,v 1.34 2000/11/12 16:59:52 monnier Exp $
 
 ;; This file is part of GNU Emacs.
 
 
 ;; Todo:
 
-;; - Spice up the minor-mode with font-lock support.
 ;; - Improve narrowed-view support.
 ;; - Improve the `compile' support (?).
-;; - Recognize pcl-cvs' special string for `cvs-execute-single'.
 ;; - Support for # comments in context->unified.
 ;; - Do a fuzzy search in diff-goto-source.
 ;; - Allow diff.el to use diff-mode.
 ;;   (i.e. new or old) file.
 ;; - Handle `diff -b' output in context->unified.
 
+;; Low priority:
+;; - Spice up the minor-mode with font-lock support.
+;; - Recognize pcl-cvs' special string for `cvs-execute-single'.
+
 ;;; Code:
 
 (eval-when-compile (require 'cl))
@@ -95,9 +97,9 @@ when editing big diffs)."
 (defvar diff-outline-regexp
   "\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)")
 
-;;;; 
+;;;;
 ;;;; keymap, menu, ...
-;;;; 
+;;;;
 
 (easy-mmode-defmap diff-mode-shared-map
   '(;; From Pavel Machek's patch-mode.
@@ -137,6 +139,7 @@ when editing big diffs)."
     ;; From compilation-minor-mode.
     ("\C-c\C-c" . diff-goto-source)
     ;; Misc operations.
+    ("\C-c\C-s" . diff-split-hunk)
     ("\C-c\C-a" . diff-apply-hunk)
     ("\C-c\C-t" . diff-test-hunk))
   "Keymap for `diff-mode'.  See also `diff-mode-shared-map'.")
@@ -145,7 +148,8 @@ when editing big diffs)."
   "Menu for `diff-mode'."
   '("Diff"
     ["Jump to Source"          diff-goto-source        t]
-    ["Apply with Ediff"                diff-ediff-patch        t]
+    ["Apply hunk"              diff-apply-hunk         t]
+    ["Apply diff with Ediff"   diff-ediff-patch        t]
     ["-----" nil nil]
     ["Reverse direction"       diff-reverse-direction  t]
     ["Context -> Unified"      diff-context->unified   t]
@@ -163,17 +167,19 @@ when editing big diffs)."
   "Keymap for `diff-minor-mode'.  See also `diff-mode-shared-map'.")
 
 
-;;;; 
+;;;;
 ;;;; font-lock support
-;;;; 
+;;;;
 
 (defface diff-header-face
   '((((type tty pc) (class color) (background light))
-     (:foreground "lightblue"))
+     (:foreground "blue1" :bold t))
     (((type tty pc) (class color) (background dark))
-     (:foreground "green"))
+     (:foreground "green" :bold t))
     (((class color) (background light))
      (:background "grey85"))
+    (((class color) (background dark))
+     (:background "grey45"))
     (t (:bold t)))
   "`diff-mode' face inherited by hunk and index header faces."
   :group 'diff-mode)
@@ -181,11 +187,13 @@ when editing big diffs)."
 
 (defface diff-file-header-face
   '((((type tty pc) (class color) (background light))
-     (:foreground "yellow"))
+     (:foreground "yellow" :bold t))
     (((type tty pc) (class color) (background dark))
-     (:foreground "cyan"))
+     (:foreground "cyan" :bold t))
     (((class color) (background light))
      (:background "grey70" :bold t))
+    (((class color) (background dark))
+     (:background "grey60" :bold t))
     (t (:bold t)))                     ; :height 1.3
   "`diff-mode' face used to highlight file header lines."
   :group 'diff-mode)
@@ -217,29 +225,39 @@ when editing big diffs)."
 
 (defface diff-changed-face
   '((((type tty pc) (class color) (background light))
-     (:foreground "magenta"))
+     (:foreground "magenta" :bold t :italic t))
     (((type tty pc) (class color) (background dark))
-     (:foreground "yellow"))
+     (:foreground "yellow" :bold t :italic t))
     (t ()))
   "`diff-mode' face used to highlight changed lines."
   :group 'diff-mode)
 (defvar diff-changed-face 'diff-changed-face)
 
-(defface diff-comment-face
-  '((t (:inherit font-lock-comment-face)))
+(defface diff-function-face
+  '((t (:inherit diff-context-face)))
+  "`diff-mode' face used to highlight function names produced by \"diff -p\"."
+  :group 'diff-mode)
+(defvar diff-function-face 'diff-function-face)
+
+(defface diff-context-face
+  '((((class color) (background light))
+     (:foreground "grey50"))
+    (((class color) (background dark))
+     (:foreground "grey70"))
+    (t ))
   "`diff-mode' face used to highlight context and other side-information."
   :group 'diff-mode)
-(defvar diff-comment-face 'diff-comment-face)
+(defvar diff-context-face 'diff-context-face)
 
 (defvar diff-font-lock-keywords
   '(("^\\(@@ -[0-9,]+ \\+[0-9,]+ @@\\)\\(.*\\)$" ;unified
      (1 diff-hunk-header-face)
-     (2 diff-comment-face))
+     (2 diff-function-face))
     ("^--- .+ ----$"           ;context
      . diff-hunk-header-face)
     ("\\(\\*\\{15\\}\\)\\(.*\\)$"      ;context
      (1 diff-hunk-header-face)
-     (2 diff-comment-face))
+     (2 diff-function-face))
     ("^\\*\\*\\* .+ \\*\\*\\*\\*". diff-hunk-header-face) ;context
     ("^\\(---\\|\\+\\+\\+\\|\\*\\*\\*\\) \\(\\S-+\\)\\(.*[^*-]\\)?\n"
      (0 diff-header-face) (2 diff-file-header-face prepend))
@@ -249,15 +267,16 @@ when editing big diffs)."
     ("^[-<].*\n" . diff-removed-face)
     ("^Index: \\(.+\\).*\n" (0 diff-header-face) (1 diff-index-face prepend))
     ("^#.*" . font-lock-string-face)
-    ("^[^-=+*!<>].*\n" . diff-comment-face)))
+    ("^[^-=+*!<>].*\n" . diff-context-face)))
 
 (defconst diff-font-lock-defaults
   '(diff-font-lock-keywords t nil nil nil (font-lock-multiline . nil)))
 
 (defvar diff-imenu-generic-expression
   ;; Prefer second name as first is most likely to be a backup or
-  ;; version-control name.
-  '((nil "\\+\\+\\+\\ \\([^\t\n]+\\)\t" 1) ; unidiffs
+  ;; version-control name.  The [\t\n] at the end of the unidiff pattern
+  ;; catches Debian source diff files (which lack the trailing date).
+  '((nil "\\+\\+\\+\\ \\([^\t\n]+\\)[\t\n]" 1) ; unidiffs
     (nil "^--- \\([^\t\n]+\\)\t.*\n\\*" 1))) ; context diffs
 
 ;;;;
@@ -272,9 +291,9 @@ when editing big diffs)."
     ("--- \\([0-9]+\\),[0-9]+ ----" nil 1)
     ("\\([0-9]+\\)\\(,[0-9]+\\)?[adc]\\([0-9]+\\)" nil 3)))
 
-;;;; 
+;;;;
 ;;;; Movement
-;;;; 
+;;;;
 
 (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)))
@@ -382,6 +401,34 @@ If the prefix ARG is given, restrict the view to the current file instead."
                       (match-beginning 3))
        (beginning-of-line)))))
 
+(defun diff-count-matches (re start end)
+  (save-excursion
+    (let ((n 0))
+      (goto-char start)
+      (while (re-search-forward re end t) (incf n))
+      n)))
+
+(defun diff-split-hunk ()
+  "Split the current (unified diff) hunk at point into two hunks."
+  (interactive)
+  (beginning-of-line)
+  (let ((pos (point))
+       (start (progn (diff-beginning-of-hunk) (point))))
+    (unless (looking-at "@@ -\\([0-9]+\\),[0-9]+ \\+\\([0-9]+\\),[0-9]+ @@")
+      (error "diff-split-hunk only works on unified context diffs"))
+    (forward-line 1)
+    (let* ((start1 (string-to-number (match-string 1)))
+          (start2 (string-to-number (match-string 2)))
+          (newstart1 (+ start1 (diff-count-matches "^[- \t]" (point) pos)))
+          (newstart2 (+ start2 (diff-count-matches "^[+ \t]" (point) pos))))
+      (goto-char pos)
+      ;; Hopefully the after-change-function will not screw us over.
+      (insert "@@ -" (number-to-string newstart1) ",1 +"
+             (number-to-string newstart2) ",1 @@\n")
+      ;; Fix the original hunk-header.
+      (diff-fixup-modifs start pos))))
+      
+
 ;;;;
 ;;;; jump to other buffers
 ;;;;
@@ -426,8 +473,8 @@ Non-nil OLD means that we want the old file."
                     (error (point-min)))))
           (header-files
            (if (looking-at "[-*][-*][-*] \\(\\S-+\\)\\(\\s-.*\\)?\n[-+][-+][-+] \\(\\S-+\\)")
-               (list (if old (match-string 1) (match-string 2))
-                     (if old (match-string 2) (match-string 1)))
+               (list (if old (match-string 1) (match-string 3))
+                     (if old (match-string 3) (match-string 1)))
              (forward-line 1) nil))
           (fs (append
                (when (save-excursion