فهرست منبع

LibLine: Support RGB colors

This also patches Userland/js.
AnotherTest 5 سال پیش
والد
کامیت
c40fd3a902
3فایلهای تغییر یافته به همراه75 افزوده شده و 37 حذف شده
  1. 22 4
      Libraries/LibLine/Editor.cpp
  2. 46 26
      Libraries/LibLine/Style.h
  3. 7 7
      Userland/js.cpp

+ 22 - 4
Libraries/LibLine/Editor.cpp

@@ -545,7 +545,7 @@ String Editor::get_line(const String& prompt)
 
                         // only apply colour to the selection if something is *actually* added to the buffer
                         if (m_last_shown_suggestion_was_complete && index == current_suggestion_index) {
-                            vt_apply_style({ Style::Foreground(Style::Color::Blue) });
+                            vt_apply_style({ Style::Foreground(Style::XtermColor::Blue) });
                             fflush(stdout);
                         }
 
@@ -973,15 +973,33 @@ Style Editor::find_applicable_style(size_t offset) const
     return {};
 }
 
+String Style::Background::to_vt_escape() const
+{
+    if (m_is_rgb) {
+        return String::format("\033[48;2;%d;%d;%dm", m_rgb_color[0], m_rgb_color[1], m_rgb_color[2]);
+    } else {
+        return String::format("\033[%dm", (u8)m_xterm_color + 40);
+    }
+}
+
+String Style::Foreground::to_vt_escape() const
+{
+    if (m_is_rgb) {
+        return String::format("\033[38;2;%d;%d;%dm", m_rgb_color[0], m_rgb_color[1], m_rgb_color[2]);
+    } else {
+        return String::format("\033[%dm", (u8)m_xterm_color + 30);
+    }
+}
+
 void Editor::vt_apply_style(const Style& style)
 {
     printf(
-        "\033[%d;%d;%d;%d;%dm",
+        "\033[%d;%d;%dm%s%s",
         style.bold() ? 1 : 22,
         style.underline() ? 4 : 24,
         style.italic() ? 3 : 23,
-        (int)style.foreground() + 30,
-        (int)style.background() + 40);
+        style.background().to_vt_escape().characters(),
+        style.foreground().to_vt_escape().characters());
 }
 
 void Editor::vt_clear_lines(size_t count_above, size_t count_below)

+ 46 - 26
Libraries/LibLine/Style.h

@@ -25,13 +25,15 @@
  */
 
 #pragma once
+#include <AK/Types.h>
+#include <AK/Vector.h>
 #include <stdlib.h>
 
 namespace Line {
 
 class Style {
 public:
-    enum class Color : int {
+    enum class XtermColor : int {
         Default = 9,
         Black = 0,
         Red,
@@ -41,15 +43,6 @@ public:
         Magenta,
         Cyan,
         White,
-        // TODO: it appears that we do not support these SGR options
-        BrightBlack = 60,
-        BrightRed,
-        BrightGreen,
-        BrightYellow,
-        BrightBlue,
-        BrightMagenta,
-        BrightCyan,
-        BrightWhite,
     };
 
     struct UnderlineTag {
@@ -58,19 +51,46 @@ public:
     };
     struct ItalicTag {
     };
-    struct Background {
-        explicit Background(Color color)
-            : m_color(color)
+    struct Color {
+        explicit Color(XtermColor color)
+            : m_xterm_color(color)
+            , m_is_rgb(false)
         {
         }
-        Color m_color;
+        Color(u8 r, u8 g, u8 b)
+            : m_rgb_color({ r, g, b })
+            , m_is_rgb(true)
+        {
+        }
+
+        XtermColor m_xterm_color { XtermColor::Default };
+        Vector<u8, 3> m_rgb_color;
+        bool m_is_rgb { false };
     };
-    struct Foreground {
-        explicit Foreground(Color color)
-            : m_color(color)
+
+    struct Background : public Color {
+        explicit Background(XtermColor color)
+            : Color(color)
         {
         }
-        Color m_color;
+        Background(u8 r, u8 g, u8 b)
+            : Color(r, g, b)
+        {
+        }
+        String to_vt_escape() const;
+    };
+
+    struct Foreground : public Color {
+        explicit Foreground(XtermColor color)
+            : Color(color)
+        {
+        }
+        Foreground(u8 r, u8 g, u8 b)
+            : Color(r, g, b)
+        {
+        }
+
+        String to_vt_escape() const;
     };
 
     static constexpr UnderlineTag Underline {};
@@ -78,31 +98,31 @@ public:
     static constexpr ItalicTag Italic {};
 
     // prepare for the horror of templates
-    template <typename T, typename... Rest>
+    template<typename T, typename... Rest>
     Style(const T& style_arg, Rest... rest)
         : Style(rest...)
     {
         set(style_arg);
     }
-    Style() {}
+    Style() { }
 
     bool underline() const { return m_underline; }
     bool bold() const { return m_bold; }
     bool italic() const { return m_italic; }
-    Color background() const { return m_background; }
-    Color foreground() const { return m_foreground; }
+    Background background() const { return m_background; }
+    Foreground foreground() const { return m_foreground; }
 
     void set(const ItalicTag&) { m_italic = true; }
     void set(const BoldTag&) { m_bold = true; }
     void set(const UnderlineTag&) { m_underline = true; }
-    void set(const Background& bg) { m_background = bg.m_color; }
-    void set(const Foreground& fg) { m_foreground = fg.m_color; }
+    void set(const Background& bg) { m_background = bg; }
+    void set(const Foreground& fg) { m_foreground = fg; }
 
 private:
     bool m_underline { false };
     bool m_bold { false };
     bool m_italic { false };
-    Color m_background { Color::Default };
-    Color m_foreground { Color::Default };
+    Background m_background { XtermColor::Default };
+    Foreground m_foreground { XtermColor::Default };
 };
 }

+ 7 - 7
Userland/js.cpp

@@ -541,10 +541,10 @@ int main(int argc, char** argv)
                 switch (token.type()) {
                 case JS::TokenType::Invalid:
                 case JS::TokenType::Eof:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Red), Line::Style::Underline });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::Red), Line::Style::Underline });
                     break;
                 case JS::TokenType::NumericLiteral:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::Magenta) });
                     break;
                 case JS::TokenType::StringLiteral:
                 case JS::TokenType::TemplateLiteralStart:
@@ -552,7 +552,7 @@ int main(int argc, char** argv)
                 case JS::TokenType::TemplateLiteralString:
                 case JS::TokenType::RegexLiteral:
                 case JS::TokenType::UnterminatedStringLiteral:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Green), Line::Style::Bold });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::Green), Line::Style::Bold });
                     break;
                 case JS::TokenType::BracketClose:
                 case JS::TokenType::BracketOpen:
@@ -609,7 +609,7 @@ int main(int argc, char** argv)
                     break;
                 case JS::TokenType::BoolLiteral:
                 case JS::TokenType::NullLiteral:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Yellow), Line::Style::Bold });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::Yellow), Line::Style::Bold });
                     break;
                 case JS::TokenType::Class:
                 case JS::TokenType::Const:
@@ -627,7 +627,7 @@ int main(int argc, char** argv)
                 case JS::TokenType::Typeof:
                 case JS::TokenType::Var:
                 case JS::TokenType::Void:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Blue), Line::Style::Bold });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::Blue), Line::Style::Bold });
                     break;
                 case JS::TokenType::Await:
                 case JS::TokenType::Case:
@@ -642,10 +642,10 @@ int main(int argc, char** argv)
                 case JS::TokenType::Try:
                 case JS::TokenType::While:
                 case JS::TokenType::Yield:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Cyan), Line::Style::Italic });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::Cyan), Line::Style::Italic });
                     break;
                 case JS::TokenType::Identifier:
-                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::White), Line::Style::Bold });
+                    stylize({ start, end }, { Line::Style::Foreground(Line::Style::XtermColor::White), Line::Style::Bold });
                 default:
                     break;
                 }