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::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 75 raw_ostream &WithColor::error() { return error(errs()); } 76 77 raw_ostream &WithColor::warning() { return warning(errs()); } 78 79 raw_ostream &WithColor::note() { return note(errs()); } 80 81 raw_ostream &WithColor::remark() { return remark(errs()); } 82 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 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 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 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 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 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 143 WithColor &WithColor::resetColor() { 144 if (colorsEnabled()) 145 OS.resetColor(); 146 return *this; 147 } 148 149 WithColor::~WithColor() { resetColor(); } 150 151 void WithColor::defaultErrorHandler(Error Err) { 152 handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) { 153 WithColor::error() << Info.message() << '\n'; 154 }); 155 } 156 157 void WithColor::defaultWarningHandler(Error Warning) { 158 handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { 159 WithColor::warning() << Info.message() << '\n'; 160 }); 161 } 162