/src/serenity/Userland/Libraries/LibLine/Style.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2020-2022, the SerenityOS developers. |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/ByteString.h> |
10 | | #include <AK/Types.h> |
11 | | #include <AK/Utf8View.h> |
12 | | #include <AK/Vector.h> |
13 | | |
14 | | namespace Line { |
15 | | |
16 | | class Style { |
17 | | public: |
18 | 0 | bool operator==(Style const&) const = default; |
19 | | |
20 | | enum class XtermColor : int { |
21 | | Default = 9, |
22 | | Black = 0, |
23 | | Red, |
24 | | Green, |
25 | | Yellow, |
26 | | Blue, |
27 | | Magenta, |
28 | | Cyan, |
29 | | White, |
30 | | Unchanged, |
31 | | }; |
32 | | |
33 | | struct AnchoredTag { |
34 | | }; |
35 | | struct UnderlineTag { |
36 | | }; |
37 | | struct BoldTag { |
38 | | }; |
39 | | struct ItalicTag { |
40 | | }; |
41 | | struct Color { |
42 | 0 | bool operator==(Color const&) const = default; |
43 | | |
44 | | explicit Color(XtermColor color) |
45 | 0 | : m_xterm_color(color) |
46 | 0 | , m_is_rgb(false) |
47 | 0 | { |
48 | 0 | } |
49 | | Color(u8 r, u8 g, u8 b) |
50 | 0 | : m_rgb_color({ r, g, b }) |
51 | 0 | , m_is_rgb(true) |
52 | 0 | { |
53 | 0 | } |
54 | | |
55 | | bool is_default() const |
56 | 0 | { |
57 | 0 | return !m_is_rgb && m_xterm_color == XtermColor::Unchanged; |
58 | 0 | } |
59 | | |
60 | | XtermColor m_xterm_color { XtermColor::Unchanged }; |
61 | | Vector<int, 3> m_rgb_color; |
62 | | bool m_is_rgb { false }; |
63 | | }; |
64 | | |
65 | | struct Background : public Color { |
66 | | explicit Background(XtermColor color) |
67 | 0 | : Color(color) |
68 | 0 | { |
69 | 0 | } |
70 | | Background(u8 r, u8 g, u8 b) |
71 | | : Color(r, g, b) |
72 | 0 | { |
73 | 0 | } |
74 | | ByteString to_vt_escape() const; |
75 | | }; |
76 | | |
77 | | struct Foreground : public Color { |
78 | | explicit Foreground(XtermColor color) |
79 | 0 | : Color(color) |
80 | 0 | { |
81 | 0 | } |
82 | | Foreground(u8 r, u8 g, u8 b) |
83 | 0 | : Color(r, g, b) |
84 | 0 | { |
85 | 0 | } |
86 | | |
87 | | ByteString to_vt_escape() const; |
88 | | }; |
89 | | |
90 | | struct Hyperlink { |
91 | 0 | bool operator==(Hyperlink const&) const = default; |
92 | | |
93 | | explicit Hyperlink(StringView link) |
94 | 0 | : m_link(link) |
95 | 0 | { |
96 | 0 | m_has_link = true; |
97 | 0 | } |
98 | | |
99 | 0 | Hyperlink() = default; |
100 | | |
101 | | ByteString to_vt_escape(bool starting) const; |
102 | | |
103 | 0 | bool is_empty() const { return !m_has_link; } |
104 | | |
105 | | ByteString m_link; |
106 | | bool m_has_link { false }; |
107 | | }; |
108 | | |
109 | | struct Mask { |
110 | | bool operator==(Mask const& other) const |
111 | 0 | { |
112 | 0 | return other.mode == mode && other.replacement == replacement; |
113 | 0 | } |
114 | | |
115 | | enum class Mode { |
116 | | ReplaceEntireSelection, |
117 | | ReplaceEachCodePointInSelection, |
118 | | }; |
119 | | explicit Mask(StringView replacement, Mode mode = Mode::ReplaceEntireSelection) |
120 | | : replacement(replacement) |
121 | | , replacement_view(this->replacement) |
122 | | , mode(mode) |
123 | 0 | { |
124 | 0 | } |
125 | | |
126 | | ByteString replacement; |
127 | | mutable Utf8View replacement_view; |
128 | | Mode mode; |
129 | | }; |
130 | | |
131 | | static constexpr UnderlineTag Underline {}; |
132 | | static constexpr BoldTag Bold {}; |
133 | | static constexpr ItalicTag Italic {}; |
134 | | static constexpr AnchoredTag Anchored {}; |
135 | | |
136 | | // Prepare for the horror of templates. |
137 | | template<typename T, typename... Rest> |
138 | | Style(T const& style_arg, Rest... rest) |
139 | 0 | : Style(rest...) |
140 | 0 | { |
141 | 0 | set(style_arg); |
142 | 0 | m_is_empty = false; |
143 | 0 | } Unexecuted instantiation: Line::Style::Style<Line::Style::BoldTag>(Line::Style::BoldTag const&) Unexecuted instantiation: Line::Style::Style<Line::Style::Foreground>(Line::Style::Foreground const&) Unexecuted instantiation: Line::Style::Style<Line::Style::Foreground, Line::Style::ItalicTag>(Line::Style::Foreground const&, Line::Style::ItalicTag) Unexecuted instantiation: Line::Style::Style<Line::Style::ItalicTag>(Line::Style::ItalicTag const&) Unexecuted instantiation: Line::Style::Style<Line::Style::Foreground, Line::Style::BoldTag>(Line::Style::Foreground const&, Line::Style::BoldTag) Unexecuted instantiation: Line::Style::Style<Line::Style::Hyperlink>(Line::Style::Hyperlink const&) Unexecuted instantiation: Line::Style::Style<Line::Style::Foreground, Line::Style::Background, Line::Style::Hyperlink>(Line::Style::Foreground const&, Line::Style::Background, Line::Style::Hyperlink) Unexecuted instantiation: Line::Style::Style<Line::Style::Background, Line::Style::Hyperlink>(Line::Style::Background const&, Line::Style::Hyperlink) Unexecuted instantiation: Line::Style::Style<Line::Style::Background>(Line::Style::Background const&) |
144 | 0 | Style() = default; |
145 | | |
146 | | static Style reset_style() |
147 | 0 | { |
148 | 0 | return { Foreground(XtermColor::Default), Background(XtermColor::Default), Hyperlink(""sv) }; |
149 | 0 | } |
150 | | |
151 | | Style unified_with(Style const& other, bool prefer_other = true) const |
152 | 0 | { |
153 | 0 | Style style = *this; |
154 | 0 | style.unify_with(other, prefer_other); |
155 | 0 | return style; |
156 | 0 | } |
157 | | |
158 | | void unify_with(Style const&, bool prefer_other = false); |
159 | | |
160 | 0 | bool underline() const { return m_underline; } |
161 | 0 | bool bold() const { return m_bold; } |
162 | 0 | bool italic() const { return m_italic; } |
163 | 0 | Background background() const { return m_background; } |
164 | 0 | Foreground foreground() const { return m_foreground; } |
165 | 0 | Hyperlink hyperlink() const { return m_hyperlink; } |
166 | 0 | Optional<Mask> mask() const { return m_mask; } |
167 | | |
168 | 0 | void unset_mask() const { m_mask = {}; } |
169 | | |
170 | 0 | void set(ItalicTag const&) { m_italic = true; } |
171 | 0 | void set(BoldTag const&) { m_bold = true; } |
172 | 0 | void set(UnderlineTag const&) { m_underline = true; } |
173 | 0 | void set(Background const& bg) { m_background = bg; } |
174 | 0 | void set(Foreground const& fg) { m_foreground = fg; } |
175 | 0 | void set(Hyperlink const& link) { m_hyperlink = link; } |
176 | 0 | void set(AnchoredTag const&) { m_is_anchored = true; } |
177 | 0 | void set(Mask const& mask) { m_mask = mask; } |
178 | | |
179 | 0 | bool is_anchored() const { return m_is_anchored; } |
180 | 0 | bool is_empty() const { return m_is_empty; } |
181 | | |
182 | | ByteString to_byte_string() const; |
183 | | |
184 | | private: |
185 | | bool m_underline { false }; |
186 | | bool m_bold { false }; |
187 | | bool m_italic { false }; |
188 | | Background m_background { XtermColor::Unchanged }; |
189 | | Foreground m_foreground { XtermColor::Unchanged }; |
190 | | Hyperlink m_hyperlink; |
191 | | mutable Optional<Mask> m_mask; |
192 | | |
193 | | bool m_is_anchored { false }; |
194 | | |
195 | | bool m_is_empty { true }; |
196 | | }; |
197 | | } |