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