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::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::BOU_UNSET ? OS.has_colors()
38 : *UseColor == cl::BOU_TRUE;
39}
40
41WithColor::AutoDetectFunctionType WithColor::AutoDetectFunction =
42 DefaultAutoDetectFunction;
43
44WithColor::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
83raw_ostream &WithColor::error() { return error(OS&: errs()); }
84
85raw_ostream &WithColor::warning() { return warning(OS&: errs()); }
86
87raw_ostream &WithColor::note() { return note(OS&: errs()); }
88
89raw_ostream &WithColor::remark() { return remark(OS&: errs()); }
90
91raw_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
101raw_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
111raw_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
121raw_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
131bool 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
143WithColor &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
150WithColor &WithColor::resetColor() {
151 if (colorsEnabled())
152 OS.resetColor();
153 return *this;
154}
155
156WithColor::~WithColor() { resetColor(); }
157
158void WithColor::defaultErrorHandler(Error Err) {
159 handleAllErrors(E: std::move(Err), Handlers: [](ErrorInfoBase &Info) {
160 WithColor::error() << Info.message() << '\n';
161 });
162}
163
164void WithColor::defaultWarningHandler(Error Warning) {
165 handleAllErrors(E: std::move(Warning), Handlers: [](ErrorInfoBase &Info) {
166 WithColor::warning() << Info.message() << '\n';
167 });
168}
169
170WithColor::AutoDetectFunctionType WithColor::defaultAutoDetectFunction() {
171 return DefaultAutoDetectFunction;
172}
173
174void WithColor::setAutoDetectFunction(
175 AutoDetectFunctionType NewAutoDetectFunction) {
176 AutoDetectFunction = NewAutoDetectFunction;
177}
178