emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/trunk r108358: Use the same diff color sche


From: Juri Linkov
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r108358: Use the same diff color scheme as in modern VCSes (bug#10181).
Date: Fri, 25 May 2012 03:55:40 +0300
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 108358
committer: Juri Linkov <address@hidden>
branch nick: trunk
timestamp: Fri 2012-05-25 03:55:40 +0300
message:
  Use the same diff color scheme as in modern VCSes (bug#10181).
  
  * lisp/vc/diff-mode.el (diff-header, diff-file-header): Remove "green"
  to avoid confusion with `diff-added' that now uses green colors.
  (diff-removed): Use shades of red.
  (diff-added): Use shades of green.
  (diff-changed): Leave just the yellow color.
  (diff-use-changed-face): New variable.
  (diff-font-lock-keywords): Use `diff-use-changed-face' to decide
  how to highlight context diff changes.
  (diff-refine-change): Use shades of yellow.
  (diff-refine-removed): New face that uses shades of red.
  (diff-refine-added): New face that uses shades of green.
  (diff-refine-hunk): Use `diff-refine-change', `diff-refine-added',
  `diff-refine-removed' in the call to `smerge-refine-subst'
  depending on the value of `diff-use-changed-face'.
  
  * lisp/vc/ediff-init.el (ediff-current-diff-A, ediff-fine-diff-A):
  Add face condition `min-colors 88' with shades of red.
  (ediff-current-diff-B, ediff-fine-diff-B): Add face condition
  `min-colors 88' with shades of green.
  (ediff-current-diff-C, ediff-fine-diff-C): Add face condition
  `min-colors 88' with shades of yellow.
  
  * lisp/vc/smerge-mode.el (smerge-mine): Use shades of red.
  (smerge-other): Use shades of green.
  (smerge-base): Use shades of yellow.
  (smerge-refined-change): Empty face.
  (smerge-refined-removed): New face that uses shades of red.
  (smerge-refined-added): New face that uses shades of green.
  (smerge-refine-subst): Rename arg `props' to `props-c'.  Add new
  args `props-r' and `props-a', and use them.  Doc fix.
  (smerge-refine): Evaluate `smerge-use-changed-face' and depending
  on its value use different faces `smerge-refined-change',
  `smerge-refined-removed', `smerge-refined-added' in the call to
  `smerge-refine-subst'.
modified:
  etc/NEWS
  lisp/ChangeLog
  lisp/vc/diff-mode.el
  lisp/vc/ediff-init.el
  lisp/vc/smerge-mode.el
=== modified file 'etc/NEWS'
--- a/etc/NEWS  2012-05-18 07:14:45 +0000
+++ b/etc/NEWS  2012-05-25 00:55:40 +0000
@@ -94,6 +94,17 @@
 
 * Changes in Specialized Modes and Packages in Emacs 24.2
 
+** Diff mode
+
+Faces for changes now use the same diff color scheme as in modern VCSes
+where deletions are displayed in red (new faces `diff-refine-removed'
+and `smerge-refined-removed' and new definition of `diff-removed'),
+insertions in green (new faces `diff-refine-added' and
+`smerge-refined-added' and new definition of `diff-added').
+The variable `diff-use-changed-face' defines whether to use
+the face `diff-changed', or `diff-removed' and `diff-added'
+to highlight changes in context diffs.
+
 ** `sh-script'
 *** Pairing of parens/quotes uses electric-pair-mode instead of skeleton-pair.
 *** `sh-electric-here-document-mode' now controls auto-insertion of here-docs.

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-05-24 20:40:19 +0000
+++ b/lisp/ChangeLog    2012-05-25 00:55:40 +0000
@@ -1,3 +1,42 @@
+2012-05-25  Juri Linkov  <address@hidden>
+
+       Use the same diff color scheme as in modern VCSes (bug#10181).
+
+       * vc/diff-mode.el (diff-header, diff-file-header): Remove "green"
+       to avoid confusion with `diff-added' that now uses green colors.
+       (diff-removed): Use shades of red.
+       (diff-added): Use shades of green.
+       (diff-changed): Leave just the yellow color.
+       (diff-use-changed-face): New variable.
+       (diff-font-lock-keywords): Use `diff-use-changed-face' to decide
+       how to highlight context diff changes.
+       (diff-refine-change): Use shades of yellow.
+       (diff-refine-removed): New face that uses shades of red.
+       (diff-refine-added): New face that uses shades of green.
+       (diff-refine-hunk): Use `diff-refine-change', `diff-refine-added',
+       `diff-refine-removed' in the call to `smerge-refine-subst'
+       depending on the value of `diff-use-changed-face'.
+
+       * vc/smerge-mode.el (smerge-mine): Use shades of red.
+       (smerge-other): Use shades of green.
+       (smerge-base): Use shades of yellow.
+       (smerge-refined-change): Empty face.
+       (smerge-refined-removed): New face that uses shades of red.
+       (smerge-refined-added): New face that uses shades of green.
+       (smerge-refine-subst): Rename arg `props' to `props-c'.  Add new
+       args `props-r' and `props-a', and use them.  Doc fix.
+       (smerge-refine): Evaluate `smerge-use-changed-face' and depending
+       on its value use different faces `smerge-refined-change',
+       `smerge-refined-removed', `smerge-refined-added' in the call to
+       `smerge-refine-subst'.
+
+       * vc/ediff-init.el (ediff-current-diff-A, ediff-fine-diff-A):
+       Add face condition `min-colors 88' with shades of red.
+       (ediff-current-diff-B, ediff-fine-diff-B): Add face condition
+       `min-colors 88' with shades of green.
+       (ediff-current-diff-C, ediff-fine-diff-C): Add face condition
+       `min-colors 88' with shades of yellow.
+
 2012-05-24  Glenn Morris  <address@hidden>
 
        * paths.el (prune-directory-list, remote-shell-program): Move to...

=== modified file 'lisp/vc/diff-mode.el'
--- a/lisp/vc/diff-mode.el      2012-04-26 08:00:47 +0000
+++ b/lisp/vc/diff-mode.el      2012-05-25 00:55:40 +0000
@@ -237,10 +237,8 @@
      :background "grey80")
     (((class color) (min-colors 88) (background dark))
      :background "grey45")
-    (((class color) (background light))
+    (((class color))
      :foreground "blue1" :weight bold)
-    (((class color) (background dark))
-     :foreground "green" :weight bold)
     (t :weight bold))
   "`diff-mode' face inherited by hunk and index header faces."
   :group 'diff-mode)
@@ -252,9 +250,7 @@
      :background "grey70" :weight bold)
     (((class color) (min-colors 88) (background dark))
      :background "grey60" :weight bold)
-    (((class color) (background light))
-     :foreground "green" :weight bold)
-    (((class color) (background dark))
+    (((class color))
      :foreground "cyan" :weight bold)
     (t :weight bold))                  ; :height 1.3
   "`diff-mode' face used to highlight file header lines."
@@ -277,14 +273,28 @@
 (defvar diff-hunk-header-face 'diff-hunk-header)
 
 (defface diff-removed
-  '((t :inherit diff-changed))
+  '((default
+     :inherit diff-changed)
+    (((class color) (min-colors 88) (background light))
+     :background "#ffdddd")
+    (((class color) (min-colors 88) (background dark))
+     :background "#553333")
+    (((class color))
+     :foreground "red"))
   "`diff-mode' face used to highlight removed lines."
   :group 'diff-mode)
 (define-obsolete-face-alias 'diff-removed-face 'diff-removed "22.1")
 (defvar diff-removed-face 'diff-removed)
 
 (defface diff-added
-  '((t :inherit diff-changed))
+  '((default
+     :inherit diff-changed)
+    (((class color) (min-colors 88) (background light))
+     :background "#ddffdd")
+    (((class color) (min-colors 88) (background dark))
+     :background "#335533")
+    (((class color))
+     :foreground "green"))
   "`diff-mode' face used to highlight added lines."
   :group 'diff-mode)
 (define-obsolete-face-alias 'diff-added-face 'diff-added "22.1")
@@ -296,10 +306,8 @@
   '((((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)
-    (((class color) (background dark))
-     :foreground "yellow" :weight bold :slant italic))
+    (((class color))
+     :foreground "yellow"))
   "`diff-mode' face used to highlight changed lines."
   :group 'diff-mode)
 (define-obsolete-face-alias 'diff-changed-face 'diff-changed "22.1")
@@ -374,6 +382,13 @@
 (defconst diff-context-mid-hunk-header-re
   "--- \\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)? ----$")
 
+(defvar diff-use-changed-face (and (face-differs-from-default-p 
diff-changed-face)
+                                  (not (face-equal diff-changed-face 
diff-added-face))
+                                  (not (face-equal diff-changed-face 
diff-removed-face)))
+  "If non-nil, use the face `diff-changed' for changed lines in context diffs.
+Otherwise, use the face `diff-removed' for removed lines,
+and the face `diff-added' for added lines.")
+
 (defvar diff-font-lock-keywords
   `((,(concat "\\(" diff-hunk-header-re-unified "\\)\\(.*\\)$")
      (1 diff-hunk-header-face) (6 diff-function-face))
@@ -393,8 +408,25 @@
     ("^\\([+>]\\)\\(.*\n\\)"
      (1 diff-indicator-added-face) (2 diff-added-face))
     ("^\\(!\\)\\(.*\n\\)"
-     (1 diff-indicator-changed-face) (2 diff-changed-face))
-    ("^Index: \\(.+\\).*\n"
+     (1 (if diff-use-changed-face
+           diff-indicator-changed-face
+         ;; Otherwise, search for `diff-context-mid-hunk-header-re' and
+         ;; if the line of context diff is above, use `diff-removed-face';
+         ;; if below, use `diff-added-face'.
+         (save-match-data
+           (let ((limit (save-excursion (diff-beginning-of-hunk))))
+             (if (save-excursion (re-search-backward 
diff-context-mid-hunk-header-re limit t))
+                 diff-indicator-added-face
+               diff-indicator-removed-face)))))
+     (2 (if diff-use-changed-face
+           diff-changed-face
+         ;; Otherwise, use the same method as above.
+         (save-match-data
+           (let ((limit (save-excursion (diff-beginning-of-hunk))))
+             (if (save-excursion (re-search-backward 
diff-context-mid-hunk-header-re limit t))
+                 diff-added-face
+               diff-removed-face))))))
+    ("^\\(?:Index\\|revno\\): \\(.+\\).*\n"
      (0 diff-header-face) (1 diff-index-face prepend))
     ("^Only in .*\n" . diff-nonexistent-face)
     ("^\\(#\\)\\(.*\\)"
@@ -1847,17 +1879,35 @@
 
 (defface diff-refine-change
   '((((class color) (min-colors 88) (background light))
-     :background "grey85")
+     :background "#ffff55")
     (((class color) (min-colors 88) (background dark))
-     :background "grey60")
-    (((class color) (background light))
-     :background "yellow")
-    (((class color) (background dark))
-     :background "green")
-    (t :weight bold))
+     :background "#aaaa22")
+    (t :inverse-video t))
   "Face used for char-based changes shown by `diff-refine-hunk'."
   :group 'diff-mode)
 
+(defface diff-refine-removed
+  '((default
+     :inherit diff-refine-change)
+    (((class color) (min-colors 88) (background light))
+     :background "#ffaaaa")
+    (((class color) (min-colors 88) (background dark))
+     :background "#aa2222"))
+  "Face used for removed characters shown by `diff-refine-hunk'."
+  :group 'diff-mode
+  :version "24.2")
+
+(defface diff-refine-added
+  '((default
+     :inherit diff-refine-change)
+    (((class color) (min-colors 88) (background light))
+     :background "#aaffaa")
+    (((class color) (min-colors 88) (background dark))
+     :background "#22aa22"))
+  "Face used for added characters shown by `diff-refine-hunk'."
+  :group 'diff-mode
+  :version "24.2")
+
 (defun diff-refine-preproc ()
   (while (re-search-forward "^[+>]" nil t)
     ;; Remove spurious changes due to the fact that one side of the hunk is
@@ -1871,7 +1921,7 @@
   )
 
 (declare-function smerge-refine-subst "smerge-mode"
-                  (beg1 end1 beg2 end2 props &optional preproc))
+                  (beg1 end1 beg2 end2 props-c &optional preproc props-r 
props-a))
 
 (defun diff-refine-hunk ()
   "Highlight changes of hunk at point at a finer granularity."
@@ -1882,7 +1932,9 @@
     (let* ((start (point))
            (style (diff-hunk-style))    ;Skips the hunk header as well.
            (beg (point))
-           (props '((diff-mode . fine) (face diff-refine-change)))
+           (props-c '((diff-mode . fine) (face diff-refine-change)))
+           (props-r '((diff-mode . fine) (face diff-refine-removed)))
+           (props-a '((diff-mode . fine) (face diff-refine-added)))
            ;; 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))))
@@ -1896,7 +1948,7 @@
                                    end t)
            (smerge-refine-subst (match-beginning 0) (match-end 1)
                                 (match-end 1) (match-end 0)
-                                props 'diff-refine-preproc)))
+                                nil 'diff-refine-preproc props-r props-a)))
         (context
          (let* ((middle (save-excursion (re-search-forward "^---")))
                 (other middle))
@@ -1908,14 +1960,17 @@
                                     (setq other (match-end 0))
                                     (match-beginning 0))
                                   other
-                                  props 'diff-refine-preproc))))
+                                  (if diff-use-changed-face props-c)
+                                  'diff-refine-preproc
+                                  (unless diff-use-changed-face props-r)
+                                  (unless diff-use-changed-face props-a)))))
         (t ;; Normal diffs.
          (let ((beg1 (1+ (point))))
            (when (re-search-forward "^---.*\n" end t)
              ;; It's a combined add&remove, so there's something to do.
              (smerge-refine-subst beg1 (match-beginning 0)
                                   (match-end 0) end
-                                  props 'diff-refine-preproc))))))))
+                                  nil 'diff-refine-preproc props-r 
props-a))))))))
 
 (defun diff-undo (&optional arg)
   "Perform `undo', ignoring the buffer's read-only status."

=== modified file 'lisp/vc/ediff-init.el'
--- a/lisp/vc/ediff-init.el     2012-04-26 03:04:36 +0000
+++ b/lisp/vc/ediff-init.el     2012-05-25 00:55:40 +0000
@@ -853,7 +853,11 @@
 
 (defface ediff-current-diff-A
   (if (featurep 'emacs)
-      '((((class color) (min-colors 16))
+      '((((class color) (min-colors 88) (background light))
+        :background "#ffdddd")
+       (((class color) (min-colors 88) (background dark))
+        :background "#553333")
+       (((class color) (min-colors 16))
         (:foreground "firebrick" :background "pale green"))
        (((class color))
         (:foreground "blue3" :background "yellow3"))
@@ -882,7 +886,11 @@
 
 (defface ediff-current-diff-B
   (if (featurep 'emacs)
-      '((((class color) (min-colors 16))
+      '((((class color) (min-colors 88) (background light))
+        :background "#ddffdd")
+       (((class color) (min-colors 88) (background dark))
+        :background "#335533")
+       (((class color) (min-colors 16))
         (:foreground "DarkOrchid" :background "Yellow"))
        (((class color))
         (:foreground "magenta3" :background "yellow3"
@@ -912,7 +920,11 @@
 
 (defface ediff-current-diff-C
   (if (featurep 'emacs)
-      '((((class color) (min-colors 16))
+      '((((class color) (min-colors 88) (background light))
+        :background "#ffffaa")
+       (((class color) (min-colors 88) (background dark))
+        :background "#888833")
+       (((class color) (min-colors 16))
         (:foreground "Navy" :background "Pink"))
        (((class color))
         (:foreground "cyan3" :background "yellow3" :weight bold))
@@ -968,7 +980,11 @@
 
 (defface ediff-fine-diff-A
   (if (featurep 'emacs)
-      '((((class color) (min-colors 16))
+      '((((class color) (min-colors 88) (background light))
+        :background "#ffaaaa")
+       (((class color) (min-colors 88) (background dark))
+        :background "#aa2222")
+       (((class color) (min-colors 16))
         (:foreground "Navy" :background "sky blue"))
        (((class color))
         (:foreground "white" :background "sky blue" :weight bold))
@@ -989,7 +1005,11 @@
 
 (defface ediff-fine-diff-B
   (if (featurep 'emacs)
-      '((((class color) (min-colors 16))
+      '((((class color) (min-colors 88) (background light))
+        :background "#aaffaa")
+       (((class color) (min-colors 88) (background dark))
+        :background "#22aa22")
+       (((class color) (min-colors 16))
         (:foreground "Black" :background "cyan"))
        (((class color))
         (:foreground "magenta3" :background "cyan3"))
@@ -1010,7 +1030,11 @@
 
 (defface ediff-fine-diff-C
   (if (featurep 'emacs)
-      '((((type pc))
+      '((((class color) (min-colors 88) (background light))
+        :background "#ffff55")
+       (((class color) (min-colors 88) (background dark))
+        :background "#aaaa22")
+       (((type pc))
         (:foreground "white" :background "Turquoise"))
        (((class color) (min-colors 16))
         (:foreground "Black" :background "Turquoise"))

=== modified file 'lisp/vc/smerge-mode.el'
--- a/lisp/vc/smerge-mode.el    2012-05-04 23:16:47 +0000
+++ b/lisp/vc/smerge-mode.el    2012-05-25 00:55:40 +0000
@@ -78,36 +78,36 @@
   :type 'boolean)
 
 (defface smerge-mine
-  '((((min-colors 88) (background light))
-     (:foreground "blue1"))
-    (((background light))
-     (:foreground "blue"))
-    (((min-colors 88) (background dark))
-     (:foreground "cyan1"))
-    (((background dark))
-     (:foreground "cyan")))
+  '((((class color) (min-colors 88) (background light))
+     :background "#ffdddd")
+    (((class color) (min-colors 88) (background dark))
+     :background "#553333")
+    (((class color))
+     :foreground "red"))
   "Face for your code."
   :group 'smerge)
 (define-obsolete-face-alias 'smerge-mine-face 'smerge-mine "22.1")
 (defvar smerge-mine-face 'smerge-mine)
 
 (defface smerge-other
-  '((((background light))
-     (:foreground "darkgreen"))
-    (((background dark))
-     (:foreground "lightgreen")))
+  '((((class color) (min-colors 88) (background light))
+     :background "#ddffdd")
+    (((class color) (min-colors 88) (background dark))
+     :background "#335533")
+    (((class color))
+     :foreground "green"))
   "Face for the other code."
   :group 'smerge)
 (define-obsolete-face-alias 'smerge-other-face 'smerge-other "22.1")
 (defvar smerge-other-face 'smerge-other)
 
 (defface smerge-base
-  '((((min-colors 88) (background light))
-     (:foreground "red1"))
-    (((background light))
-     (:foreground "red"))
-    (((background dark))
-     (:foreground "orange")))
+  '((((class color) (min-colors 88) (background light))
+     :background "#ffffaa")
+    (((class color) (min-colors 88) (background dark))
+     :background "#888833")
+    (((class color))
+     :foreground "yellow"))
   "Face for the base code."
   :group 'smerge)
 (define-obsolete-face-alias 'smerge-base-face 'smerge-base "22.1")
@@ -124,10 +124,34 @@
 (defvar smerge-markers-face 'smerge-markers)
 
 (defface smerge-refined-change
-  '((t :background "yellow"))
+  '((t nil))
   "Face used for char-based changes shown by `smerge-refine'."
   :group 'smerge)
 
+(defface smerge-refined-removed
+  '((default
+     :inherit smerge-refined-change)
+    (((class color) (min-colors 88) (background light))
+     :background "#ffaaaa")
+    (((class color) (min-colors 88) (background dark))
+     :background "#aa2222")
+    (t :inverse-video t))
+  "Face used for removed characters shown by `smerge-refine'."
+  :group 'smerge
+  :version "24.2")
+
+(defface smerge-refined-added
+  '((default
+     :inherit smerge-refined-change)
+    (((class color) (min-colors 88) (background light))
+     :background "#aaffaa")
+    (((class color) (min-colors 88) (background dark))
+     :background "#22aa22")
+    (t :inverse-video t))
+  "Face used for added characters shown by `smerge-refine'."
+  :group 'smerge
+  :version "24.2")
+
 (easy-mmode-defmap smerge-basic-map
   `(("n" . smerge-next)
     ("p" . smerge-prev)
@@ -980,9 +1004,17 @@
           (dolist (x props) (overlay-put ol (car x) (cdr x)))
           ol)))))
 
-(defun smerge-refine-subst (beg1 end1 beg2 end2 props &optional preproc)
+(defun smerge-refine-subst (beg1 end1 beg2 end2 props-c &optional preproc 
props-r props-a)
   "Show fine differences in the two regions BEG1..END1 and BEG2..END2.
-PROPS is an alist of properties to put (via overlays) on the changes.
+PROPS-C is an alist of properties to put (via overlays) on the changes.
+PROPS-R is an alist of properties to put on removed characters.
+PROPS-A is an alist of properties to put on added characters.
+If PROPS-R and PROPS-A are nil, put PROPS-C on all changes.
+If PROPS-C is nil, but PROPS-R and PROPS-A are non-nil,
+put PROPS-A on added characters, PROPS-R on removed characters.
+If PROPS-C, PROPS-R and PROPS-A are non-nil, put PROPS-C on changed characters,
+PROPS-A on added characters, and PROPS-R on removed characters.
+
 If non-nil, PREPROC is called with no argument in a buffer that contains
 a copy of a region, just before preparing it to for `diff'.  It can be
 used to replace chars to try and eliminate some spurious differences."
@@ -1026,10 +1058,18 @@
                     (m5 (match-string 5)))
                 (when (memq op '(?d ?c))
                   (setq last1
-                        (smerge-refine-highlight-change buf beg1 m1 m2 props)))
+                        (smerge-refine-highlight-change
+                        buf beg1 m1 m2
+                        ;; Try to use props-c only for changed chars,
+                        ;; fallback to props-r for changed/removed chars,
+                        ;; but if props-r is nil then fallback to props-c.
+                        (or (and (eq op '?c) props-c) props-r props-c))))
                 (when (memq op '(?a ?c))
                   (setq last2
-                        (smerge-refine-highlight-change buf beg2 m4 m5 
props))))
+                        (smerge-refine-highlight-change
+                        buf beg2 m4 m5
+                        ;; Same logic as for removed chars above.
+                        (or (and (eq op '?c) props-c) props-a props-c)))))
               (forward-line 1)                            ;Skip hunk header.
               (and (re-search-forward "^[0-9]" nil 'move) ;Skip hunk body.
                    (goto-char (match-beginning 0))))
@@ -1081,7 +1121,11 @@
                    ((eq (match-end 3) (match-beginning 3)) 3)
                    (t 2)))
   (let ((n1 (if (eq part 1) 2 1))
-        (n2 (if (eq part 3) 2 3)))
+        (n2 (if (eq part 3) 2 3))
+       (smerge-use-changed-face
+        (and (face-differs-from-default-p 'smerge-refined-change)
+             (not (face-equal 'smerge-refined-change 'smerge-refined-added))
+             (not (face-equal 'smerge-refined-change 
'smerge-refined-removed)))))
     (smerge-ensure-match n1)
     (smerge-ensure-match n2)
     (with-silent-modifications
@@ -1090,8 +1134,13 @@
                          (cons (buffer-chars-modified-tick) part)))
     (smerge-refine-subst (match-beginning n1) (match-end n1)
                          (match-beginning n2)  (match-end n2)
-                         '((smerge . refine)
-                           (face . smerge-refined-change)))))
+                         (if smerge-use-changed-face
+                            '((smerge . refine) (face . 
smerge-refined-change)))
+                        nil
+                        (unless smerge-use-changed-face
+                          '((smerge . refine) (face . smerge-refined-removed)))
+                        (unless smerge-use-changed-face
+                          '((smerge . refine) (face . 
smerge-refined-added))))))
 
 (defun smerge-diff (n1 n2)
   (smerge-match-conflict)


reply via email to

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