emacs-diffs
[Top][All Lists]
Advanced

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

master 89f399324b: * lisp/vc/diff-mode.el (diff--font-lock-prettify): bu


From: Stefan Monnier
Subject: master 89f399324b: * lisp/vc/diff-mode.el (diff--font-lock-prettify): bug#54034
Date: Mon, 21 Feb 2022 17:22:41 -0500 (EST)

branch: master
commit 89f399324be874d42747ff67ee3bcdbe0b6120d1
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    * lisp/vc/diff-mode.el (diff--font-lock-prettify): bug#54034
    
    Handle Git's output when deleting and creating empty files, as well as
    when the diff is not shown because the file is considered as binary.
---
 lisp/vc/diff-mode.el | 67 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 49 insertions(+), 18 deletions(-)

diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index fb622bb6f9..c28321e473 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -2615,29 +2615,60 @@ fixed, visit it in a buffer."
                                'display spec)))))
     ;; Mimicks the output of Magit's diff.
     ;; FIXME: This has only been tested with Git's diff output.
+    ;; FIXME: Add support for Git's "rename from/to"?
     (while (re-search-forward "^diff " limit t)
+      ;; We split the regexp match into a search plus a looking-at because
+      ;; we want to use LIMIT for the search but we still want to match
+      ;; all the header's lines even if LIMIT falls in the middle of it.
       (when (save-excursion
               (forward-line 0)
               (looking-at
                (eval-when-compile
-                 (concat "diff.*\n"
-                         "\\(?:\\(?:new file\\|deleted\\).*\n\\)?"
-                         "\\(?:index.*\n\\)?"
-                         "--- \\(?:" null-device "\\|[ab]/\\(.*\\)\\)\n"
-                         "\\+\\+\\+ \\(?:" null-device 
"\\|[ab]/\\(.*\\)\\)\n"))))
-        (add-text-properties
-         (match-beginning 0) (1- (match-end 0))
-         (list 'display
-               (propertize
-                (cond
-                 ((null (match-string 1))
-                  (concat "new file  " (match-string 2)))
-                 ((null (match-string 2))
-                  (concat "deleted  " (match-string 1)))
-                 (t
-                  (concat "modified  " (match-string 1))))
-                'face '(diff-file-header diff-header))
-               'font-lock-multiline t)))))
+                 (let* ((index "\\(?:index.*\n\\)?")
+                        (file4 (concat
+                                "\\(?:" null-device "\\|[ab]/\\(?4:.*\\)\\)"))
+                        (file5 (concat
+                                "\\(?:" null-device "\\|[ab]/\\(?5:.*\\)\\)"))
+                        (header (concat "--- " file4 "\n"
+                                        "\\+\\+\\+ " file5 "\n"))
+                        (binary (concat
+                                 "Binary files " file4
+                                 " and " file5 " \\(?7:differ\\)\n"))
+                        (horb (concat "\\(?:" header "\\|" binary "\\)")))
+                   (concat "diff.*?\\(?: a/\\(.*?\\) b/\\(.*\\)\\)?\n"
+                           "\\(?:"
+                           ;; For new/deleted files, there might be no
+                           ;; header (and no hunk) if the file is/was empty.
+                           "\\(?3:new\\(?6:\\)\\|deleted\\) file.*\n"
+                           index "\\(?:" horb "\\)?"
+                           ;; Normal case.
+                           "\\|" index horb "\\)")))))
+        ;; The file names can be extracted either from the `diff' line
+        ;; or from the two header lines.  Prefer the header line info if
+        ;; available since the `diff' line is ambiguous in case the
+        ;; file names include " b/" or " a/".
+        (let ((oldfile (or (match-string 4) (match-string 1)))
+              (newfile (or (match-string 5) (match-string 2)))
+              (kind (if (match-beginning 7) " BINARY"
+                      (unless (or (match-beginning 4) (match-beginning 5))
+                       " empty"))))
+          (add-text-properties
+           (match-beginning 0) (1- (match-end 0))
+           (list 'display
+                 (propertize
+                  (cond
+                   ((match-beginning 3)
+                    (concat (capitalize (match-string 3)) kind " file"
+                            "  "
+                            (if (match-beginning 6) newfile oldfile)))
+                   ((null (match-string 4))
+                    (concat "New" kind " file  " newfile))
+                   ((null (match-string 2))
+                    (concat "Deleted" kind " file  " oldfile))
+                   (t
+                    (concat "Modified" kind " file  " oldfile)))
+                  'face '(diff-file-header diff-header))
+                 'font-lock-multiline t))))))
   nil)
 
 ;;; Syntax highlighting from font-lock



reply via email to

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