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 19 cl::OptionCategory &llvm::getColorCategory() { 20 static cl::OptionCategory ColorCategory("Color Options"); 21 return ColorCategory; 22 } 23 namespace { 24 struct 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(cl::BOU_UNSET)); 30 } 31 }; 32 } // namespace 33 static ManagedStatic<cl::opt<cl::boolOrDefault>, CreateUseColor> UseColor; 34 void llvm::initWithColorOptions() { *UseColor; } 35 36 static bool DefaultAutoDetectFunction(const raw_ostream &OS) { 37 return *UseColor == cl::BOU_UNSET ? OS.has_colors() 38 : *UseColor == cl::BOU_TRUE; 39 } 40 41 WithColor::AutoDetectFunctionType WithColor::AutoDetectFunction = 42 DefaultAutoDetectFunction; 43 44 WithColor::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(raw_ostream::YELLOW); 51 break; 52 case HighlightColor::String: 53 OS.changeColor(raw_ostream::GREEN); 54 break; 55 case HighlightColor::Tag: 56 OS.changeColor(raw_ostream::BLUE); 57 break; 58 case HighlightColor::Attribute: 59 OS.changeColor(raw_ostream::CYAN); 60 break; 61 case HighlightColor::Enumerator: 62 OS.changeColor(raw_ostream::MAGENTA); 63 break; 64 case HighlightColor::Macro: 65 OS.changeColor(raw_ostream::RED); 66 break; 67 case HighlightColor::Error: 68 OS.changeColor(raw_ostream::RED, true); 69 break; 70 case HighlightColor::Warning: 71 OS.changeColor(raw_ostream::MAGENTA, true); 72 break; 73 case HighlightColor::Note: 74 OS.changeColor(raw_ostream::BLACK, true); 75 break; 76 case HighlightColor::Remark: 77 OS.changeColor(raw_ostream::BLUE, true); 78 break; 79 } 80 } 81 } 82 83 raw_ostream &WithColor::error() { return error(errs()); } 84 85 raw_ostream &WithColor::warning() { return warning(errs()); } 86 87 raw_ostream &WithColor::note() { return note(errs()); } 88 89 raw_ostream &WithColor::remark() { return remark(errs()); } 90 91 raw_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 101 raw_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 111 raw_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 121 raw_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 131 bool 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 143 WithColor &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 150 WithColor &WithColor::resetColor() { 151 if (colorsEnabled()) 152 OS.resetColor(); 153 return *this; 154 } 155 156 WithColor::~WithColor() { resetColor(); } 157 158 void WithColor::defaultErrorHandler(Error Err) { 159 handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) { 160 WithColor::error() << Info.message() << '\n'; 161 }); 162 } 163 164 void WithColor::defaultWarningHandler(Error Warning) { 165 handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { 166 WithColor::warning() << Info.message() << '\n'; 167 }); 168 } 169 170 WithColor::AutoDetectFunctionType WithColor::defaultAutoDetectFunction() { 171 return DefaultAutoDetectFunction; 172 } 173 174 void WithColor::setAutoDetectFunction( 175 AutoDetectFunctionType NewAutoDetectFunction) { 176 AutoDetectFunction = NewAutoDetectFunction; 177 } 178