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