169217539SJonas Devlieghere //===- WithColor.cpp ------------------------------------------------------===//
269217539SJonas Devlieghere //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
669217539SJonas Devlieghere //
769217539SJonas Devlieghere //===----------------------------------------------------------------------===//
869217539SJonas Devlieghere 
969217539SJonas Devlieghere #include "llvm/Support/WithColor.h"
1076374573SMehdi Amini 
1176374573SMehdi Amini #include "DebugOptions.h"
1276374573SMehdi Amini 
13ddc6ec94SSimon Pilgrim #include "llvm/Support/CommandLine.h"
14ba7a92c0SNico Weber #include "llvm/Support/Error.h"
1576374573SMehdi Amini #include "llvm/Support/ManagedStatic.h"
1669217539SJonas Devlieghere 
1769217539SJonas Devlieghere using namespace llvm;
1869217539SJonas Devlieghere 
getColorCategory()1976374573SMehdi Amini cl::OptionCategory &llvm::getColorCategory() {
2076374573SMehdi Amini   static cl::OptionCategory ColorCategory("Color Options");
2176374573SMehdi Amini   return ColorCategory;
2276374573SMehdi Amini }
2376374573SMehdi Amini namespace {
2476374573SMehdi Amini struct CreateUseColor {
call__anonefd7f0a70111::CreateUseColor2576374573SMehdi Amini   static void *call() {
2676374573SMehdi Amini     return new cl::opt<cl::boolOrDefault>(
2776374573SMehdi Amini         "color", cl::cat(getColorCategory()),
2827126f52SJonas Devlieghere         cl::desc("Use colors in output (default=autodetect)"),
2969217539SJonas Devlieghere         cl::init(cl::BOU_UNSET));
3076374573SMehdi Amini   }
3176374573SMehdi Amini };
3276374573SMehdi Amini } // namespace
3376374573SMehdi Amini static ManagedStatic<cl::opt<cl::boolOrDefault>, CreateUseColor> UseColor;
initWithColorOptions()3476374573SMehdi Amini void llvm::initWithColorOptions() { *UseColor; }
3569217539SJonas Devlieghere 
DefaultAutoDetectFunction(const raw_ostream & OS)36*4429cf14SJonas Devlieghere static bool DefaultAutoDetectFunction(const raw_ostream &OS) {
37*4429cf14SJonas Devlieghere   return *UseColor == cl::BOU_UNSET ? OS.has_colors()
38*4429cf14SJonas Devlieghere                                     : *UseColor == cl::BOU_TRUE;
39*4429cf14SJonas Devlieghere }
40*4429cf14SJonas Devlieghere 
41*4429cf14SJonas Devlieghere WithColor::AutoDetectFunctionType WithColor::AutoDetectFunction =
42*4429cf14SJonas Devlieghere     DefaultAutoDetectFunction;
43*4429cf14SJonas Devlieghere 
WithColor(raw_ostream & OS,HighlightColor Color,ColorMode Mode)44550b5995SJonas Devlieghere WithColor::WithColor(raw_ostream &OS, HighlightColor Color, ColorMode Mode)
45550b5995SJonas Devlieghere     : OS(OS), Mode(Mode) {
4669217539SJonas Devlieghere   // Detect color from terminal type unless the user passed the --color option.
473e66509fSJoel E. Denny   if (colorsEnabled()) {
4869217539SJonas Devlieghere     switch (Color) {
4969217539SJonas Devlieghere     case HighlightColor::Address:
5069217539SJonas Devlieghere       OS.changeColor(raw_ostream::YELLOW);
5169217539SJonas Devlieghere       break;
5269217539SJonas Devlieghere     case HighlightColor::String:
5369217539SJonas Devlieghere       OS.changeColor(raw_ostream::GREEN);
5469217539SJonas Devlieghere       break;
5569217539SJonas Devlieghere     case HighlightColor::Tag:
5669217539SJonas Devlieghere       OS.changeColor(raw_ostream::BLUE);
5769217539SJonas Devlieghere       break;
5869217539SJonas Devlieghere     case HighlightColor::Attribute:
5969217539SJonas Devlieghere       OS.changeColor(raw_ostream::CYAN);
6069217539SJonas Devlieghere       break;
6169217539SJonas Devlieghere     case HighlightColor::Enumerator:
6269217539SJonas Devlieghere       OS.changeColor(raw_ostream::MAGENTA);
6369217539SJonas Devlieghere       break;
6469217539SJonas Devlieghere     case HighlightColor::Macro:
6569217539SJonas Devlieghere       OS.changeColor(raw_ostream::RED);
6669217539SJonas Devlieghere       break;
6769217539SJonas Devlieghere     case HighlightColor::Error:
6869217539SJonas Devlieghere       OS.changeColor(raw_ostream::RED, true);
6969217539SJonas Devlieghere       break;
7069217539SJonas Devlieghere     case HighlightColor::Warning:
7169217539SJonas Devlieghere       OS.changeColor(raw_ostream::MAGENTA, true);
7269217539SJonas Devlieghere       break;
7369217539SJonas Devlieghere     case HighlightColor::Note:
7469217539SJonas Devlieghere       OS.changeColor(raw_ostream::BLACK, true);
7569217539SJonas Devlieghere       break;
763e66509fSJoel E. Denny     case HighlightColor::Remark:
773e66509fSJoel E. Denny       OS.changeColor(raw_ostream::BLUE, true);
783e66509fSJoel E. Denny       break;
7969217539SJonas Devlieghere     }
8069217539SJonas Devlieghere   }
8169217539SJonas Devlieghere }
8269217539SJonas Devlieghere 
error()836be1f019SJonas Devlieghere raw_ostream &WithColor::error() { return error(errs()); }
846be1f019SJonas Devlieghere 
warning()856be1f019SJonas Devlieghere raw_ostream &WithColor::warning() { return warning(errs()); }
866be1f019SJonas Devlieghere 
note()876be1f019SJonas Devlieghere raw_ostream &WithColor::note() { return note(errs()); }
886be1f019SJonas Devlieghere 
remark()893e66509fSJoel E. Denny raw_ostream &WithColor::remark() { return remark(errs()); }
903e66509fSJoel E. Denny 
error(raw_ostream & OS,StringRef Prefix,bool DisableColors)913e66509fSJoel E. Denny raw_ostream &WithColor::error(raw_ostream &OS, StringRef Prefix,
923e66509fSJoel E. Denny                               bool DisableColors) {
93578c0494SJonas Devlieghere   if (!Prefix.empty())
94578c0494SJonas Devlieghere     OS << Prefix << ": ";
95550b5995SJonas Devlieghere   return WithColor(OS, HighlightColor::Error,
96550b5995SJonas Devlieghere                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
97550b5995SJonas Devlieghere              .get()
983e66509fSJoel E. Denny          << "error: ";
993072b130SJonas Devlieghere }
1003072b130SJonas Devlieghere 
warning(raw_ostream & OS,StringRef Prefix,bool DisableColors)1013e66509fSJoel E. Denny raw_ostream &WithColor::warning(raw_ostream &OS, StringRef Prefix,
1023e66509fSJoel E. Denny                                 bool DisableColors) {
103578c0494SJonas Devlieghere   if (!Prefix.empty())
104578c0494SJonas Devlieghere     OS << Prefix << ": ";
105550b5995SJonas Devlieghere   return WithColor(OS, HighlightColor::Warning,
106550b5995SJonas Devlieghere                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
107550b5995SJonas Devlieghere              .get()
1083e66509fSJoel E. Denny          << "warning: ";
1093072b130SJonas Devlieghere }
1103072b130SJonas Devlieghere 
note(raw_ostream & OS,StringRef Prefix,bool DisableColors)1113e66509fSJoel E. Denny raw_ostream &WithColor::note(raw_ostream &OS, StringRef Prefix,
1123e66509fSJoel E. Denny                              bool DisableColors) {
113578c0494SJonas Devlieghere   if (!Prefix.empty())
114578c0494SJonas Devlieghere     OS << Prefix << ": ";
115550b5995SJonas Devlieghere   return WithColor(OS, HighlightColor::Note,
116550b5995SJonas Devlieghere                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
117550b5995SJonas Devlieghere              .get()
118550b5995SJonas Devlieghere          << "note: ";
1193072b130SJonas Devlieghere }
1203072b130SJonas Devlieghere 
remark(raw_ostream & OS,StringRef Prefix,bool DisableColors)1213e66509fSJoel E. Denny raw_ostream &WithColor::remark(raw_ostream &OS, StringRef Prefix,
1223e66509fSJoel E. Denny                                bool DisableColors) {
1233e66509fSJoel E. Denny   if (!Prefix.empty())
1243e66509fSJoel E. Denny     OS << Prefix << ": ";
125550b5995SJonas Devlieghere   return WithColor(OS, HighlightColor::Remark,
126550b5995SJonas Devlieghere                    DisableColors ? ColorMode::Disable : ColorMode::Auto)
127550b5995SJonas Devlieghere              .get()
1283e66509fSJoel E. Denny          << "remark: ";
1293e66509fSJoel E. Denny }
1303e66509fSJoel E. Denny 
colorsEnabled()1313e66509fSJoel E. Denny bool WithColor::colorsEnabled() {
132550b5995SJonas Devlieghere   switch (Mode) {
133550b5995SJonas Devlieghere   case ColorMode::Enable:
134550b5995SJonas Devlieghere     return true;
135550b5995SJonas Devlieghere   case ColorMode::Disable:
1363e66509fSJoel E. Denny     return false;
137550b5995SJonas Devlieghere   case ColorMode::Auto:
138*4429cf14SJonas Devlieghere     return AutoDetectFunction(OS);
139550b5995SJonas Devlieghere   }
140550b5995SJonas Devlieghere   llvm_unreachable("All cases handled above.");
1413e66509fSJoel E. Denny }
1423e66509fSJoel E. Denny 
changeColor(raw_ostream::Colors Color,bool Bold,bool BG)1434d41c332SRui Ueyama WithColor &WithColor::changeColor(raw_ostream::Colors Color, bool Bold,
1444d41c332SRui Ueyama                                   bool BG) {
1453e66509fSJoel E. Denny   if (colorsEnabled())
1464d41c332SRui Ueyama     OS.changeColor(Color, Bold, BG);
1473e66509fSJoel E. Denny   return *this;
1483e66509fSJoel E. Denny }
1493e66509fSJoel E. Denny 
resetColor()1503e66509fSJoel E. Denny WithColor &WithColor::resetColor() {
1513e66509fSJoel E. Denny   if (colorsEnabled())
15269217539SJonas Devlieghere     OS.resetColor();
1533e66509fSJoel E. Denny   return *this;
15469217539SJonas Devlieghere }
1553e66509fSJoel E. Denny 
~WithColor()1563e66509fSJoel E. Denny WithColor::~WithColor() { resetColor(); }
157c187364dSAlexey Lapshin 
defaultErrorHandler(Error Err)158c187364dSAlexey Lapshin void WithColor::defaultErrorHandler(Error Err) {
159c187364dSAlexey Lapshin   handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) {
160c187364dSAlexey Lapshin     WithColor::error() << Info.message() << '\n';
161c187364dSAlexey Lapshin   });
162c187364dSAlexey Lapshin }
163c187364dSAlexey Lapshin 
defaultWarningHandler(Error Warning)164c187364dSAlexey Lapshin void WithColor::defaultWarningHandler(Error Warning) {
165c187364dSAlexey Lapshin   handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) {
166c187364dSAlexey Lapshin     WithColor::warning() << Info.message() << '\n';
167c187364dSAlexey Lapshin   });
168c187364dSAlexey Lapshin }
169*4429cf14SJonas Devlieghere 
defaultAutoDetectFunction()170*4429cf14SJonas Devlieghere WithColor::AutoDetectFunctionType WithColor::defaultAutoDetectFunction() {
171*4429cf14SJonas Devlieghere   return DefaultAutoDetectFunction;
172*4429cf14SJonas Devlieghere }
173*4429cf14SJonas Devlieghere 
setAutoDetectFunction(AutoDetectFunctionType NewAutoDetectFunction)174*4429cf14SJonas Devlieghere void WithColor::setAutoDetectFunction(
175*4429cf14SJonas Devlieghere     AutoDetectFunctionType NewAutoDetectFunction) {
176*4429cf14SJonas Devlieghere   AutoDetectFunction = NewAutoDetectFunction;
177*4429cf14SJonas Devlieghere }
178