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 #include "llvm/Support/CommandLine.h"
11 
12 using namespace llvm;
13 
14 cl::OptionCategory llvm::ColorCategory("Color Options");
15 
16 static cl::opt<cl::boolOrDefault>
17     UseColor("color", cl::cat(ColorCategory),
18              cl::desc("Use colors in output (default=autodetect)"),
19              cl::init(cl::BOU_UNSET));
20 
WithColor(raw_ostream & OS,HighlightColor Color,ColorMode Mode)21 WithColor::WithColor(raw_ostream &OS, HighlightColor Color, ColorMode Mode)
22     : OS(OS), Mode(Mode) {
23   // Detect color from terminal type unless the user passed the --color option.
24   if (colorsEnabled()) {
25     switch (Color) {
26     case HighlightColor::Address:
27       OS.changeColor(raw_ostream::YELLOW);
28       break;
29     case HighlightColor::String:
30       OS.changeColor(raw_ostream::GREEN);
31       break;
32     case HighlightColor::Tag:
33       OS.changeColor(raw_ostream::BLUE);
34       break;
35     case HighlightColor::Attribute:
36       OS.changeColor(raw_ostream::CYAN);
37       break;
38     case HighlightColor::Enumerator:
39       OS.changeColor(raw_ostream::MAGENTA);
40       break;
41     case HighlightColor::Macro:
42       OS.changeColor(raw_ostream::RED);
43       break;
44     case HighlightColor::Error:
45       OS.changeColor(raw_ostream::RED, true);
46       break;
47     case HighlightColor::Warning:
48       OS.changeColor(raw_ostream::MAGENTA, true);
49       break;
50     case HighlightColor::Note:
51       OS.changeColor(raw_ostream::BLACK, true);
52       break;
53     case HighlightColor::Remark:
54       OS.changeColor(raw_ostream::BLUE, true);
55       break;
56     }
57   }
58 }
59 
error()60 raw_ostream &WithColor::error() { return error(errs()); }
61 
warning()62 raw_ostream &WithColor::warning() { return warning(errs()); }
63 
note()64 raw_ostream &WithColor::note() { return note(errs()); }
65 
remark()66 raw_ostream &WithColor::remark() { return remark(errs()); }
67 
error(raw_ostream & OS,StringRef Prefix,bool DisableColors)68 raw_ostream &WithColor::error(raw_ostream &OS, StringRef Prefix,
69                               bool DisableColors) {
70   if (!Prefix.empty())
71     OS << Prefix << ": ";
72   return WithColor(OS, HighlightColor::Error,
73                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
74              .get()
75          << "error: ";
76 }
77 
warning(raw_ostream & OS,StringRef Prefix,bool DisableColors)78 raw_ostream &WithColor::warning(raw_ostream &OS, StringRef Prefix,
79                                 bool DisableColors) {
80   if (!Prefix.empty())
81     OS << Prefix << ": ";
82   return WithColor(OS, HighlightColor::Warning,
83                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
84              .get()
85          << "warning: ";
86 }
87 
note(raw_ostream & OS,StringRef Prefix,bool DisableColors)88 raw_ostream &WithColor::note(raw_ostream &OS, StringRef Prefix,
89                              bool DisableColors) {
90   if (!Prefix.empty())
91     OS << Prefix << ": ";
92   return WithColor(OS, HighlightColor::Note,
93                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
94              .get()
95          << "note: ";
96 }
97 
remark(raw_ostream & OS,StringRef Prefix,bool DisableColors)98 raw_ostream &WithColor::remark(raw_ostream &OS, StringRef Prefix,
99                                bool DisableColors) {
100   if (!Prefix.empty())
101     OS << Prefix << ": ";
102   return WithColor(OS, HighlightColor::Remark,
103                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
104              .get()
105          << "remark: ";
106 }
107 
colorsEnabled()108 bool WithColor::colorsEnabled() {
109   switch (Mode) {
110   case ColorMode::Enable:
111     return true;
112   case ColorMode::Disable:
113     return false;
114   case ColorMode::Auto:
115     return UseColor == cl::BOU_UNSET ? OS.has_colors()
116                                      : UseColor == cl::BOU_TRUE;
117   }
118   llvm_unreachable("All cases handled above.");
119 }
120 
changeColor(raw_ostream::Colors Color,bool Bold,bool BG)121 WithColor &WithColor::changeColor(raw_ostream::Colors Color, bool Bold,
122                                   bool BG) {
123   if (colorsEnabled())
124     OS.changeColor(Color, Bold, BG);
125   return *this;
126 }
127 
resetColor()128 WithColor &WithColor::resetColor() {
129   if (colorsEnabled())
130     OS.resetColor();
131   return *this;
132 }
133 
~WithColor()134 WithColor::~WithColor() { resetColor(); }
135 
defaultErrorHandler(Error Err)136 void WithColor::defaultErrorHandler(Error Err) {
137   handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) {
138     WithColor::error() << Info.message() << '\n';
139   });
140 }
141 
defaultWarningHandler(Error Warning)142 void WithColor::defaultWarningHandler(Error Warning) {
143   handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) {
144     WithColor::warning() << Info.message() << '\n';
145   });
146 }
147