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