Index: llvm/include/llvm/Support/WithColor.h =================================================================== --- llvm/include/llvm/Support/WithColor.h +++ llvm/include/llvm/Support/WithColor.h @@ -11,6 +11,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" +#include namespace llvm { @@ -110,6 +111,70 @@ WithColor &resetColor(); }; +/// A color settings saved in NestableWithColorContext. +struct ColorState { + raw_ostream::Colors Color; + bool Bold; + bool BG; + + ColorState(raw_ostream::Colors Color, bool Bold, bool BG) + : Color(Color), Bold(Bold), BG(BG) {} +}; + +/// A context for NestableWithColor which holds saved colors. +class NestableWithColorContext { + std::stack NestedColors; + +public: + void pushColor(raw_ostream::Colors Color, bool Bold, bool BG) { + NestedColors.emplace(Color, Bold, BG); + } + + void popColor() { NestedColors.pop(); } + + bool empty() { return NestedColors.empty(); } + + const ColorState ¤tColor() { return NestedColors.top(); } +}; + +/// A RAII object which temporarily changes the color in a specific stream just +/// like WithColor, but supports restoring the previous color in the given +/// context. +/// +/// Usage: +/// +/// NestableWithColorContext Ctx; +/// NestableWithColor WNC1(outs(), Ctx, raw_ostream::RED, ...); +/// { +/// NestableWithColor WNC2(outs(), Ctx, raw_ostream::BLUE, ...); +/// outs() << "A blue-colored text."; +/// // WNC2 is destroyed and WNC1's color is restored here. +/// } +/// outs() << "A red-colored text."; +/// +class NestableWithColor { + raw_ostream &OS; + NestableWithColorContext &Ctx; + bool DisableColors; + +public: + NestableWithColor(raw_ostream &OS, NestableWithColorContext &Ctx, + raw_ostream::Colors Color = raw_ostream::SAVEDCOLOR, + bool Bold = false, bool BG = false, + bool DisableColors = false); + ~NestableWithColor(); + + template NestableWithColor &operator<<(T &O) { + OS << O; + return *this; + } + + template NestableWithColor &operator<<(const T &O) { + OS << O; + return *this; + } +}; + } // end namespace llvm #endif // LLVM_LIB_DEBUGINFO_WITHCOLOR_H Index: llvm/lib/Support/WithColor.cpp =================================================================== --- llvm/lib/Support/WithColor.cpp +++ llvm/lib/Support/WithColor.cpp @@ -118,3 +118,33 @@ } WithColor::~WithColor() { resetColor(); } + +NestableWithColor::NestableWithColor(raw_ostream &OS, + NestableWithColorContext &Ctx, + raw_ostream::Colors Color, bool Bold, + bool BG, bool DisableColors) + : OS(OS), Ctx(Ctx), DisableColors(DisableColors) { + if (DisableColors) + return; + + Ctx.pushColor(Color, Bold, BG); + if (Color == raw_ostream::RESET) + OS.resetColor(); + else + OS.changeColor(Color, Bold, BG); +} + +NestableWithColor::~NestableWithColor() { + if (DisableColors) + return; + + Ctx.popColor(); + // Restore the previous color if it exists. + if (!Ctx.empty()) { + const ColorState &State = Ctx.currentColor(); + if (State.Color == raw_ostream::RESET) + OS.resetColor(); + else + OS.changeColor(State.Color, State.Bold, State.BG); + } +}