emacs-diffs
[Top][All Lists]
Advanced

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

master 0fa2279 2/4: Add support for 256-color and 24bit ANSI colors in a


From: Lars Ingebrigtsen
Subject: master 0fa2279 2/4: Add support for 256-color and 24bit ANSI colors in ansi-color
Date: Tue, 5 Oct 2021 02:55:42 -0400 (EDT)

branch: master
commit 0fa2279b90bf5a638d8377032b71135e1374e8fb
Author: Miha Rihtaršič <miha@kamnitnik.top>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Add support for 256-color and 24bit ANSI colors in ansi-color
    
    * lisp/ansi-color.el (ansi-color--code-as-hex): New function to
    convert from 256-color and 24-bit ANSI codes.
    (ansi-color--face-vec-face): Add support for ANSI color codes greater
    than 16
    (ansi-color--update-face-vec): Add support for ANSI codes 38 and 48
    which can specify 256-color and 24bit ANSI colors.
    
    * test/lisp/ansi-color-tests.el (ansi-color-tests--strings): Add tests
    for ANSI codes 38 and 34
---
 etc/NEWS                      |  7 +++++
 lisp/ansi-color.el            | 70 +++++++++++++++++++++++++++++++++++--------
 test/lisp/ansi-color-tests.el | 12 ++++++--
 3 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index ef8d95a..c2dde4e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -82,6 +82,13 @@ mode (instead of at load time).
 +++
 *** New macro 'with-memoization' provides a very primitive form of memoization
 
+** ansi-color.el
+
+---
+*** Support for ANSI 256-color and 24-bit colors.
+256-color and 24-bit color codes are now handled by ANSI color
+filters and displayed with the specified color.
+
 
 * New Modes and Packages in Emacs 29.1
 
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 3878c73..aaaf60c 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -594,22 +594,24 @@ code.  It is usually stored as the car of the variable
     (when-let ((fg (car colors)))
       (push
        `(:foreground
-         ,(face-foreground
-           (aref (if (or bright (>= fg 8))
-                     ansi-color-bright-colors-vector
-                   ansi-color-normal-colors-vector)
-                 (mod fg 8))
-           nil 'default))
+         ,(or (ansi-color--code-as-hex fg)
+              (face-foreground
+               (aref (if (or bright (>= fg 8))
+                         ansi-color-bright-colors-vector
+                       ansi-color-normal-colors-vector)
+                     (mod fg 8))
+               nil 'default)))
        faces))
     (when-let ((bg (cadr colors)))
       (push
        `(:background
-         ,(face-background
-           (aref (if (or bright (>= bg 8))
-                     ansi-color-bright-colors-vector
-                   ansi-color-normal-colors-vector)
-                 (mod bg 8))
-           nil 'default))
+         ,(or (ansi-color--code-as-hex bg)
+              (face-background
+               (aref (if (or bright (>= bg 8))
+                         ansi-color-bright-colors-vector
+                       ansi-color-normal-colors-vector)
+                     (mod bg 8))
+               nil 'default)))
        faces))
 
     (let ((i 8))
@@ -622,6 +624,32 @@ code.  It is usually stored as the car of the variable
         faces
       (car faces))))
 
+(defun ansi-color--code-as-hex (color)
+  "Convert COLOR to hexadecimal string representation.
+COLOR is an ANSI color code.  If it is between 16 and 255
+inclusive, it corresponds to a color from an 8-bit color cube.
+If it is greater or equal than 256, it is subtracted by 256 to
+directly specify a 24-bit color.
+
+Return a hexadecimal string, specifying the color, or nil, if
+COLOR is less than 16."
+  (cond
+   ((< color 16) nil)
+   ((>= color 256) (format "#%06X" (- color 256)))
+   ((>= color 232) ;; Grayscale
+    (format "#%06X" (* #x010101 (+ 8 (* 10 (- color 232))))))
+   (t ;; 6x6x6 color cube
+    (setq color (- color 16))
+    (let ((res 0)
+          (frac (* 6 6)))
+      (while (<= 1 frac)                ; Repeat 3 times
+        (setq res (* res #x000100))
+        (let ((color-num (mod (/ color frac) 6)))
+          (unless (zerop color-num)
+            (setq res (+ res #x37 (* #x28 color-num)))))
+        (setq frac (/ frac 6)))
+      (format "#%06X" res)))))
+
 ;; Working with regions
 
 (defvar-local ansi-color-context-region nil
@@ -907,7 +935,23 @@ unset all properties and colors."
          (let ((r (mod new 10))
                (cell (if (memq q '(3 9)) colors (cdr colors))))
            (pcase r
-             (8 (setq do-clear t))
+             (8
+              (pcase (funcall iterator)
+                (5 (setq new (setcar cell (funcall iterator)))
+                   (setq do-clear (or (null new) (>= new 256))))
+                (2
+                 (let ((red (funcall iterator))
+                       (green (funcall iterator))
+                       (blue (funcall iterator)))
+                   (if (and red green blue
+                            (progn
+                              (setq new (+ (* #x010000 red)
+                                           (* #x000100 green)
+                                           (* #x000001 blue)))
+                              (<= new #xFFFFFF)))
+                       (setcar cell (+ 256 new))
+                     (setq do-clear t))))
+                (_ (setq do-clear t))))
              (9 (setcar cell nil))
              (_ (setcar cell (+ (if (memq q '(3 4)) 0 8) r))))))
         (_ (setq do-clear t)))
diff --git a/test/lisp/ansi-color-tests.el b/test/lisp/ansi-color-tests.el
index 953fdff..16a1ba4 100644
--- a/test/lisp/ansi-color-tests.el
+++ b/test/lisp/ansi-color-tests.el
@@ -27,7 +27,8 @@
 
 (defvar ansi-color-tests--strings
   (let ((bright-yellow (face-foreground 'ansi-color-bright-yellow nil 
'default))
-        (yellow (face-foreground 'ansi-color-yellow nil 'default)))
+        (yellow (face-foreground 'ansi-color-yellow nil 'default))
+        (custom-color "#87FFFF"))
     `(("Hello World" "Hello World")
       ("\e[33mHello World\e[0m" "Hello World"
        (:foreground ,yellow))
@@ -51,7 +52,14 @@
        (ansi-color-bold (:foreground ,bright-yellow)))
       ("\e[1m\e[3m\e[5mbold italics blink\e[0m" "bold italics blink"
        (ansi-color-bold ansi-color-italic ansi-color-slow-blink))
-      ("\e[10munrecognized\e[0m" "unrecognized"))))
+      ("\e[10munrecognized\e[0m" "unrecognized")
+      ("\e[38;5;3;1mHello World\e[0m" "Hello World"
+       (ansi-color-bold (:foreground ,yellow))
+       (ansi-color-bold (:foreground ,bright-yellow)))
+      ("\e[48;5;123;1mHello World\e[0m" "Hello World"
+       (ansi-color-bold (:background ,custom-color)))
+      ("\e[48;2;135;255;255;1mHello World\e[0m" "Hello World"
+       (ansi-color-bold (:background ,custom-color))))))
 
 (ert-deftest ansi-color-apply-on-region-test ()
   (pcase-dolist (`(,input ,text ,face) ansi-color-tests--strings)



reply via email to

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