1 | //===- WithColor.cpp ------------------------------------------------------===// |
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 | #include "llvm/Support/WithColor.h" |
10 | |
11 | #include "DebugOptions.h" |
12 | |
13 | #include "llvm/Support/CommandLine.h" |
14 | #include "llvm/Support/Error.h" |
15 | #include "llvm/Support/ManagedStatic.h" |
16 | |
17 | using namespace llvm; |
18 | |
19 | cl::OptionCategory &llvm::getColorCategory() { |
20 | static cl::OptionCategory ColorCategory("Color Options" ); |
21 | return ColorCategory; |
22 | } |
23 | namespace { |
24 | struct CreateUseColor { |
25 | static void *call() { |
26 | return new cl::opt<cl::boolOrDefault>( |
27 | "color" , cl::cat(getColorCategory()), |
28 | cl::desc("Use colors in output (default=autodetect)" ), |
29 | cl::init(Val: cl::BOU_UNSET)); |
30 | } |
31 | }; |
32 | } // namespace |
33 | static ManagedStatic<cl::opt<cl::boolOrDefault>, CreateUseColor> UseColor; |
34 | void llvm::initWithColorOptions() { *UseColor; } |
35 | |
36 | static bool DefaultAutoDetectFunction(const raw_ostream &OS) { |
37 | return *UseColor == cl::BOU_UNSET ? OS.has_colors() |
38 | : *UseColor == cl::BOU_TRUE; |
39 | } |
40 | |
41 | WithColor::AutoDetectFunctionType WithColor::AutoDetectFunction = |
42 | DefaultAutoDetectFunction; |
43 | |
44 | WithColor::WithColor(raw_ostream &OS, HighlightColor Color, ColorMode Mode) |
45 | : OS(OS), Mode(Mode) { |
46 | // Detect color from terminal type unless the user passed the --color option. |
47 | if (colorsEnabled()) { |
48 | switch (Color) { |
49 | case HighlightColor::Address: |
50 | OS.changeColor(Color: raw_ostream::YELLOW); |
51 | break; |
52 | case HighlightColor::String: |
53 | OS.changeColor(Color: raw_ostream::GREEN); |
54 | break; |
55 | case HighlightColor::Tag: |
56 | OS.changeColor(Color: raw_ostream::BLUE); |
57 | break; |
58 | case HighlightColor::Attribute: |
59 | OS.changeColor(Color: raw_ostream::CYAN); |
60 | break; |
61 | case HighlightColor::Enumerator: |
62 | OS.changeColor(Color: raw_ostream::MAGENTA); |
63 | break; |
64 | case HighlightColor::Macro: |
65 | OS.changeColor(Color: raw_ostream::RED); |
66 | break; |
67 | case HighlightColor::Error: |
68 | OS.changeColor(Color: raw_ostream::RED, Bold: true); |
69 | break; |
70 | case HighlightColor::Warning: |
71 | OS.changeColor(Color: raw_ostream::MAGENTA, Bold: true); |
72 | break; |
73 | case HighlightColor::Note: |
74 | OS.changeColor(Color: raw_ostream::BLACK, Bold: true); |
75 | break; |
76 | case HighlightColor::Remark: |
77 | OS.changeColor(Color: raw_ostream::BLUE, Bold: true); |
78 | break; |
79 | } |
80 | } |
81 | } |
82 | |
83 | raw_ostream &WithColor::error() { return error(OS&: errs()); } |
84 | |
85 | raw_ostream &WithColor::warning() { return warning(OS&: errs()); } |
86 | |
87 | raw_ostream &WithColor::note() { return note(OS&: errs()); } |
88 | |
89 | raw_ostream &WithColor::() { return remark(OS&: errs()); } |
90 | |
91 | raw_ostream &WithColor::error(raw_ostream &OS, StringRef Prefix, |
92 | bool DisableColors) { |
93 | if (!Prefix.empty()) |
94 | OS << Prefix << ": " ; |
95 | return WithColor(OS, HighlightColor::Error, |
96 | DisableColors ? ColorMode::Disable : ColorMode::Auto) |
97 | .get() |
98 | << "error: " ; |
99 | } |
100 | |
101 | raw_ostream &WithColor::warning(raw_ostream &OS, StringRef Prefix, |
102 | bool DisableColors) { |
103 | if (!Prefix.empty()) |
104 | OS << Prefix << ": " ; |
105 | return WithColor(OS, HighlightColor::Warning, |
106 | DisableColors ? ColorMode::Disable : ColorMode::Auto) |
107 | .get() |
108 | << "warning: " ; |
109 | } |
110 | |
111 | raw_ostream &WithColor::note(raw_ostream &OS, StringRef Prefix, |
112 | bool DisableColors) { |
113 | if (!Prefix.empty()) |
114 | OS << Prefix << ": " ; |
115 | return WithColor(OS, HighlightColor::Note, |
116 | DisableColors ? ColorMode::Disable : ColorMode::Auto) |
117 | .get() |
118 | << "note: " ; |
119 | } |
120 | |
121 | raw_ostream &WithColor::(raw_ostream &OS, StringRef Prefix, |
122 | bool DisableColors) { |
123 | if (!Prefix.empty()) |
124 | OS << Prefix << ": " ; |
125 | return WithColor(OS, HighlightColor::Remark, |
126 | DisableColors ? ColorMode::Disable : ColorMode::Auto) |
127 | .get() |
128 | << "remark: " ; |
129 | } |
130 | |
131 | bool WithColor::colorsEnabled() { |
132 | switch (Mode) { |
133 | case ColorMode::Enable: |
134 | return true; |
135 | case ColorMode::Disable: |
136 | return false; |
137 | case ColorMode::Auto: |
138 | return AutoDetectFunction(OS); |
139 | } |
140 | llvm_unreachable("All cases handled above." ); |
141 | } |
142 | |
143 | WithColor &WithColor::changeColor(raw_ostream::Colors Color, bool Bold, |
144 | bool BG) { |
145 | if (colorsEnabled()) |
146 | OS.changeColor(Color, Bold, BG); |
147 | return *this; |
148 | } |
149 | |
150 | WithColor &WithColor::resetColor() { |
151 | if (colorsEnabled()) |
152 | OS.resetColor(); |
153 | return *this; |
154 | } |
155 | |
156 | WithColor::~WithColor() { resetColor(); } |
157 | |
158 | void WithColor::defaultErrorHandler(Error Err) { |
159 | handleAllErrors(E: std::move(Err), Handlers: [](ErrorInfoBase &Info) { |
160 | WithColor::error() << Info.message() << '\n'; |
161 | }); |
162 | } |
163 | |
164 | void WithColor::defaultWarningHandler(Error Warning) { |
165 | handleAllErrors(E: std::move(Warning), Handlers: [](ErrorInfoBase &Info) { |
166 | WithColor::warning() << Info.message() << '\n'; |
167 | }); |
168 | } |
169 | |
170 | WithColor::AutoDetectFunctionType WithColor::defaultAutoDetectFunction() { |
171 | return DefaultAutoDetectFunction; |
172 | } |
173 | |
174 | void WithColor::setAutoDetectFunction( |
175 | AutoDetectFunctionType NewAutoDetectFunction) { |
176 | AutoDetectFunction = NewAutoDetectFunction; |
177 | } |
178 | |