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
getColorCategory()19 cl::OptionCategory &llvm::getColorCategory() {
20 static cl::OptionCategory ColorCategory("Color Options");
21 return ColorCategory;
22 }
23 namespace {
24 struct CreateUseColor {
call__anon710f93770111::CreateUseColor25 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(cl::BOU_UNSET));
30 }
31 };
32 } // namespace
33 static ManagedStatic<cl::opt<cl::boolOrDefault>, CreateUseColor> UseColor;
initWithColorOptions()34 void llvm::initWithColorOptions() { *UseColor; }
35
DefaultAutoDetectFunction(const raw_ostream & OS)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
WithColor(raw_ostream & OS,HighlightColor Color,ColorMode Mode)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(raw_ostream::YELLOW);
51 break;
52 case HighlightColor::String:
53 OS.changeColor(raw_ostream::GREEN);
54 break;
55 case HighlightColor::Tag:
56 OS.changeColor(raw_ostream::BLUE);
57 break;
58 case HighlightColor::Attribute:
59 OS.changeColor(raw_ostream::CYAN);
60 break;
61 case HighlightColor::Enumerator:
62 OS.changeColor(raw_ostream::MAGENTA);
63 break;
64 case HighlightColor::Macro:
65 OS.changeColor(raw_ostream::RED);
66 break;
67 case HighlightColor::Error:
68 OS.changeColor(raw_ostream::RED, true);
69 break;
70 case HighlightColor::Warning:
71 OS.changeColor(raw_ostream::MAGENTA, true);
72 break;
73 case HighlightColor::Note:
74 OS.changeColor(raw_ostream::BLACK, true);
75 break;
76 case HighlightColor::Remark:
77 OS.changeColor(raw_ostream::BLUE, true);
78 break;
79 }
80 }
81 }
82
error()83 raw_ostream &WithColor::error() { return error(errs()); }
84
warning()85 raw_ostream &WithColor::warning() { return warning(errs()); }
86
note()87 raw_ostream &WithColor::note() { return note(errs()); }
88
remark()89 raw_ostream &WithColor::remark() { return remark(errs()); }
90
error(raw_ostream & OS,StringRef Prefix,bool DisableColors)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
warning(raw_ostream & OS,StringRef Prefix,bool DisableColors)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
note(raw_ostream & OS,StringRef Prefix,bool DisableColors)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
remark(raw_ostream & OS,StringRef Prefix,bool DisableColors)121 raw_ostream &WithColor::remark(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
colorsEnabled()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
changeColor(raw_ostream::Colors Color,bool Bold,bool BG)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
resetColor()150 WithColor &WithColor::resetColor() {
151 if (colorsEnabled())
152 OS.resetColor();
153 return *this;
154 }
155
~WithColor()156 WithColor::~WithColor() { resetColor(); }
157
defaultErrorHandler(Error Err)158 void WithColor::defaultErrorHandler(Error Err) {
159 handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) {
160 WithColor::error() << Info.message() << '\n';
161 });
162 }
163
defaultWarningHandler(Error Warning)164 void WithColor::defaultWarningHandler(Error Warning) {
165 handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) {
166 WithColor::warning() << Info.message() << '\n';
167 });
168 }
169
defaultAutoDetectFunction()170 WithColor::AutoDetectFunctionType WithColor::defaultAutoDetectFunction() {
171 return DefaultAutoDetectFunction;
172 }
173
setAutoDetectFunction(AutoDetectFunctionType NewAutoDetectFunction)174 void WithColor::setAutoDetectFunction(
175 AutoDetectFunctionType NewAutoDetectFunction) {
176 AutoDetectFunction = NewAutoDetectFunction;
177 }
178