1 | //===---------------------AnsiTerminal.h ------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLDB_UTILITY_ANSITERMINAL_H |
10 | #define LLDB_UTILITY_ANSITERMINAL_H |
11 | |
12 | #define ANSI_FG_COLOR_BLACK 30 |
13 | #define ANSI_FG_COLOR_RED 31 |
14 | #define ANSI_FG_COLOR_GREEN 32 |
15 | #define ANSI_FG_COLOR_YELLOW 33 |
16 | #define ANSI_FG_COLOR_BLUE 34 |
17 | #define ANSI_FG_COLOR_PURPLE 35 |
18 | #define ANSI_FG_COLOR_CYAN 36 |
19 | #define ANSI_FG_COLOR_WHITE 37 |
20 | |
21 | #define ANSI_FG_COLOR_BRIGHT_BLACK 90 |
22 | #define ANSI_FG_COLOR_BRIGHT_RED 91 |
23 | #define ANSI_FG_COLOR_BRIGHT_GREEN 92 |
24 | #define ANSI_FG_COLOR_BRIGHT_YELLOW 93 |
25 | #define ANSI_FG_COLOR_BRIGHT_BLUE 94 |
26 | #define ANSI_FG_COLOR_BRIGHT_PURPLE 95 |
27 | #define ANSI_FG_COLOR_BRIGHT_CYAN 96 |
28 | #define ANSI_FG_COLOR_BRIGHT_WHITE 97 |
29 | |
30 | #define ANSI_BG_COLOR_BLACK 40 |
31 | #define ANSI_BG_COLOR_RED 41 |
32 | #define ANSI_BG_COLOR_GREEN 42 |
33 | #define ANSI_BG_COLOR_YELLOW 43 |
34 | #define ANSI_BG_COLOR_BLUE 44 |
35 | #define ANSI_BG_COLOR_PURPLE 45 |
36 | #define ANSI_BG_COLOR_CYAN 46 |
37 | #define ANSI_BG_COLOR_WHITE 47 |
38 | |
39 | #define ANSI_BG_COLOR_BRIGHT_BLACK 100 |
40 | #define ANSI_BG_COLOR_BRIGHT_RED 101 |
41 | #define ANSI_BG_COLOR_BRIGHT_GREEN 102 |
42 | #define ANSI_BG_COLOR_BRIGHT_YELLOW 103 |
43 | #define ANSI_BG_COLOR_BRIGHT_BLUE 104 |
44 | #define ANSI_BG_COLOR_BRIGHT_PURPLE 105 |
45 | #define ANSI_BG_COLOR_BRIGHT_CYAN 106 |
46 | #define ANSI_BG_COLOR_BRIGHT_WHITE 107 |
47 | |
48 | #define ANSI_SPECIAL_FRAMED 51 |
49 | #define ANSI_SPECIAL_ENCIRCLED 52 |
50 | |
51 | #define ANSI_CTRL_NORMAL 0 |
52 | #define ANSI_CTRL_BOLD 1 |
53 | #define ANSI_CTRL_FAINT 2 |
54 | #define ANSI_CTRL_ITALIC 3 |
55 | #define ANSI_CTRL_UNDERLINE 4 |
56 | #define ANSI_CTRL_SLOW_BLINK 5 |
57 | #define ANSI_CTRL_FAST_BLINK 6 |
58 | #define ANSI_CTRL_IMAGE_NEGATIVE 7 |
59 | #define ANSI_CTRL_CONCEAL 8 |
60 | #define ANSI_CTRL_CROSSED_OUT 9 |
61 | |
62 | #define ANSI_ESC_START "\033[" |
63 | #define ANSI_ESC_END "m" |
64 | |
65 | #define ANSI_STR(s) #s |
66 | #define ANSI_DEF_STR(s) ANSI_STR(s) |
67 | |
68 | #define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END |
69 | |
70 | #define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END |
71 | #define ANSI_2_CTRL(ctrl1, ctrl2) "\033["##ctrl1 ";"##ctrl2 ANSI_ESC_END |
72 | |
73 | #include "llvm/ADT/ArrayRef.h" |
74 | #include "llvm/ADT/STLExtras.h" |
75 | #include "llvm/ADT/StringRef.h" |
76 | |
77 | #include <string> |
78 | |
79 | namespace lldb_private { |
80 | |
81 | namespace ansi { |
82 | |
83 | inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, |
84 | bool do_color = true) { |
85 | // Convert "${ansi.XXX}" tokens to ansi values or clear them if do_color is |
86 | // false. |
87 | // clang-format off |
88 | static const struct { |
89 | const char *name; |
90 | const char *value; |
91 | } g_color_tokens[] = { |
92 | #define _TO_STR2(_val) #_val |
93 | #define _TO_STR(_val) _TO_STR2(_val) |
94 | {.name: "fg.black}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END}, |
95 | {.name: "fg.red}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END}, |
96 | {.name: "fg.green}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END}, |
97 | {.name: "fg.yellow}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END}, |
98 | {.name: "fg.blue}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END}, |
99 | {.name: "fg.purple}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END}, |
100 | {.name: "fg.cyan}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END}, |
101 | {.name: "fg.white}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END}, |
102 | {.name: "fg.bright.black}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_BLACK) ANSI_ESC_END}, |
103 | {.name: "fg.bright.red}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_RED) ANSI_ESC_END}, |
104 | {.name: "fg.bright.green}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_GREEN) ANSI_ESC_END}, |
105 | {.name: "fg.bright.yellow}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_YELLOW) ANSI_ESC_END}, |
106 | {.name: "fg.bright.blue}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_BLUE) ANSI_ESC_END}, |
107 | {.name: "fg.bright.purple}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_PURPLE) ANSI_ESC_END}, |
108 | {.name: "fg.bright.cyan}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_CYAN) ANSI_ESC_END}, |
109 | {.name: "fg.bright.white}" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_WHITE) ANSI_ESC_END}, |
110 | {.name: "bg.black}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END}, |
111 | {.name: "bg.red}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END}, |
112 | {.name: "bg.green}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END}, |
113 | {.name: "bg.yellow}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END}, |
114 | {.name: "bg.blue}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END}, |
115 | {.name: "bg.purple}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END}, |
116 | {.name: "bg.cyan}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END}, |
117 | {.name: "bg.white}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END}, |
118 | {.name: "bg.bright.black}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_BLACK) ANSI_ESC_END}, |
119 | {.name: "bg.bright.red}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_RED) ANSI_ESC_END}, |
120 | {.name: "bg.bright.green}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_GREEN) ANSI_ESC_END}, |
121 | {.name: "bg.bright.yellow}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_YELLOW) ANSI_ESC_END}, |
122 | {.name: "bg.bright.blue}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_BLUE) ANSI_ESC_END}, |
123 | {.name: "bg.bright.purple}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_PURPLE) ANSI_ESC_END}, |
124 | {.name: "bg.bright.cyan}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_CYAN) ANSI_ESC_END}, |
125 | {.name: "bg.bright.white}" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_WHITE) ANSI_ESC_END}, |
126 | {.name: "normal}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END}, |
127 | {.name: "bold}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END}, |
128 | {.name: "faint}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END}, |
129 | {.name: "italic}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END}, |
130 | {.name: "underline}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END}, |
131 | {.name: "slow-blink}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END}, |
132 | {.name: "fast-blink}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END}, |
133 | {.name: "negative}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END}, |
134 | {.name: "conceal}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END}, |
135 | {.name: "crossed-out}" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END}, |
136 | #undef _TO_STR |
137 | #undef _TO_STR2 |
138 | }; |
139 | // clang-format on |
140 | auto codes = llvm::ArrayRef(g_color_tokens); |
141 | |
142 | static const char tok_hdr[] = "${ansi." ; |
143 | |
144 | std::string fmt; |
145 | while (!format.empty()) { |
146 | llvm::StringRef left, right; |
147 | std::tie(args&: left, args&: right) = format.split(Separator: tok_hdr); |
148 | |
149 | fmt += left; |
150 | |
151 | if (left == format && right.empty()) { |
152 | // The header was not found. Just exit. |
153 | break; |
154 | } |
155 | |
156 | bool found_code = false; |
157 | for (const auto &code : codes) { |
158 | if (!right.consume_front(Prefix: code.name)) |
159 | continue; |
160 | |
161 | if (do_color) |
162 | fmt.append(s: code.value); |
163 | found_code = true; |
164 | break; |
165 | } |
166 | format = right; |
167 | // If we haven't found a valid replacement value, we just copy the string |
168 | // to the result without any modifications. |
169 | if (!found_code) |
170 | fmt.append(s: tok_hdr); |
171 | } |
172 | return fmt; |
173 | } |
174 | } |
175 | } // namespace lldb_private |
176 | |
177 | #endif |
178 | |