| //===- WithColor.cpp ------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Support/WithColor.h" |
| |
| #include "DebugOptions.h" |
| |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/Support/ManagedStatic.h" |
| |
| using namespace llvm; |
| |
| cl::OptionCategory &llvm::getColorCategory() { |
| static cl::OptionCategory ColorCategory("Color Options"); |
| return ColorCategory; |
| } |
| namespace { |
| struct CreateUseColor { |
| static void *call() { |
| return new cl::opt<cl::boolOrDefault>( |
| "color", cl::cat(getColorCategory()), |
| cl::desc("Use colors in output (default=autodetect)"), |
| cl::init(cl::BOU_UNSET)); |
| } |
| }; |
| } // namespace |
| static ManagedStatic<cl::opt<cl::boolOrDefault>, CreateUseColor> UseColor; |
| void llvm::initWithColorOptions() { *UseColor; } |
| |
| static bool DefaultAutoDetectFunction(const raw_ostream &OS) { |
| return *UseColor == cl::BOU_UNSET ? OS.has_colors() |
| : *UseColor == cl::BOU_TRUE; |
| } |
| |
| WithColor::AutoDetectFunctionType WithColor::AutoDetectFunction = |
| DefaultAutoDetectFunction; |
| |
| WithColor::WithColor(raw_ostream &OS, HighlightColor Color, ColorMode Mode) |
| : OS(OS), Mode(Mode) { |
| // Detect color from terminal type unless the user passed the --color option. |
| if (colorsEnabled()) { |
| switch (Color) { |
| case HighlightColor::Address: |
| OS.changeColor(raw_ostream::YELLOW); |
| break; |
| case HighlightColor::String: |
| OS.changeColor(raw_ostream::GREEN); |
| break; |
| case HighlightColor::Tag: |
| OS.changeColor(raw_ostream::BLUE); |
| break; |
| case HighlightColor::Attribute: |
| OS.changeColor(raw_ostream::CYAN); |
| break; |
| case HighlightColor::Enumerator: |
| OS.changeColor(raw_ostream::MAGENTA); |
| break; |
| case HighlightColor::Macro: |
| OS.changeColor(raw_ostream::RED); |
| break; |
| case HighlightColor::Error: |
| OS.changeColor(raw_ostream::RED, true); |
| break; |
| case HighlightColor::Warning: |
| OS.changeColor(raw_ostream::MAGENTA, true); |
| break; |
| case HighlightColor::Note: |
| OS.changeColor(raw_ostream::BLACK, true); |
| break; |
| case HighlightColor::Remark: |
| OS.changeColor(raw_ostream::BLUE, true); |
| break; |
| } |
| } |
| } |
| |
| raw_ostream &WithColor::error() { return error(errs()); } |
| |
| raw_ostream &WithColor::warning() { return warning(errs()); } |
| |
| raw_ostream &WithColor::note() { return note(errs()); } |
| |
| raw_ostream &WithColor::remark() { return remark(errs()); } |
| |
| raw_ostream &WithColor::error(raw_ostream &OS, StringRef Prefix, |
| bool DisableColors) { |
| if (!Prefix.empty()) |
| OS << Prefix << ": "; |
| return WithColor(OS, HighlightColor::Error, |
| DisableColors ? ColorMode::Disable : ColorMode::Auto) |
| .get() |
| << "error: "; |
| } |
| |
| raw_ostream &WithColor::warning(raw_ostream &OS, StringRef Prefix, |
| bool DisableColors) { |
| if (!Prefix.empty()) |
| OS << Prefix << ": "; |
| return WithColor(OS, HighlightColor::Warning, |
| DisableColors ? ColorMode::Disable : ColorMode::Auto) |
| .get() |
| << "warning: "; |
| } |
| |
| raw_ostream &WithColor::note(raw_ostream &OS, StringRef Prefix, |
| bool DisableColors) { |
| if (!Prefix.empty()) |
| OS << Prefix << ": "; |
| return WithColor(OS, HighlightColor::Note, |
| DisableColors ? ColorMode::Disable : ColorMode::Auto) |
| .get() |
| << "note: "; |
| } |
| |
| raw_ostream &WithColor::remark(raw_ostream &OS, StringRef Prefix, |
| bool DisableColors) { |
| if (!Prefix.empty()) |
| OS << Prefix << ": "; |
| return WithColor(OS, HighlightColor::Remark, |
| DisableColors ? ColorMode::Disable : ColorMode::Auto) |
| .get() |
| << "remark: "; |
| } |
| |
| bool WithColor::colorsEnabled() { |
| switch (Mode) { |
| case ColorMode::Enable: |
| return true; |
| case ColorMode::Disable: |
| return false; |
| case ColorMode::Auto: |
| return AutoDetectFunction(OS); |
| } |
| llvm_unreachable("All cases handled above."); |
| } |
| |
| WithColor &WithColor::changeColor(raw_ostream::Colors Color, bool Bold, |
| bool BG) { |
| if (colorsEnabled()) |
| OS.changeColor(Color, Bold, BG); |
| return *this; |
| } |
| |
| WithColor &WithColor::resetColor() { |
| if (colorsEnabled()) |
| OS.resetColor(); |
| return *this; |
| } |
| |
| WithColor::~WithColor() { resetColor(); } |
| |
| void WithColor::defaultErrorHandler(Error Err) { |
| handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) { |
| WithColor::error() << Info.message() << '\n'; |
| }); |
| } |
| |
| void WithColor::defaultWarningHandler(Error Warning) { |
| handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { |
| WithColor::warning() << Info.message() << '\n'; |
| }); |
| } |
| |
| WithColor::AutoDetectFunctionType WithColor::defaultAutoDetectFunction() { |
| return DefaultAutoDetectFunction; |
| } |
| |
| void WithColor::setAutoDetectFunction( |
| AutoDetectFunctionType NewAutoDetectFunction) { |
| AutoDetectFunction = NewAutoDetectFunction; |
| } |