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
79namespace lldb_private {
80
81namespace ansi {
82
83inline 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

source code of lldb/include/lldb/Utility/AnsiTerminal.h