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