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#include "llvm/Support/CommandLine.h"
11#include "llvm/Support/Error.h"
12
13using namespace llvm;
14
15cl::OptionCategory llvm::ColorCategory("Color Options");
16
17static cl::opt<cl::boolOrDefault>
18    UseColor("color", cl::cat(ColorCategory),
19             cl::desc("Use colors in output (default=autodetect)"),
20             cl::init(cl::BOU_UNSET));
21
22WithColor::WithColor(raw_ostream &OS, HighlightColor Color, ColorMode Mode)
23    : OS(OS), Mode(Mode) {
24  // Detect color from terminal type unless the user passed the --color option.
25  if (colorsEnabled()) {
26    switch (Color) {
27    case HighlightColor::Address:
28      OS.changeColor(raw_ostream::YELLOW);
29      break;
30    case HighlightColor::String:
31      OS.changeColor(raw_ostream::GREEN);
32      break;
33    case HighlightColor::Tag:
34      OS.changeColor(raw_ostream::BLUE);
35      break;
36    case HighlightColor::Attribute:
37      OS.changeColor(raw_ostream::CYAN);
38      break;
39    case HighlightColor::Enumerator:
40      OS.changeColor(raw_ostream::MAGENTA);
41      break;
42    case HighlightColor::Macro:
43      OS.changeColor(raw_ostream::RED);
44      break;
45    case HighlightColor::Error:
46      OS.changeColor(raw_ostream::RED, true);
47      break;
48    case HighlightColor::Warning:
49      OS.changeColor(raw_ostream::MAGENTA, true);
50      break;
51    case HighlightColor::Note:
52      OS.changeColor(raw_ostream::BLACK, true);
53      break;
54    case HighlightColor::Remark:
55      OS.changeColor(raw_ostream::BLUE, true);
56      break;
57    }
58  }
59}
60
61raw_ostream &WithColor::error() { return error(errs()); }
62
63raw_ostream &WithColor::warning() { return warning(errs()); }
64
65raw_ostream &WithColor::note() { return note(errs()); }
66
67raw_ostream &WithColor::remark() { return remark(errs()); }
68
69raw_ostream &WithColor::error(raw_ostream &OS, StringRef Prefix,
70                              bool DisableColors) {
71  if (!Prefix.empty())
72    OS << Prefix << ": ";
73  return WithColor(OS, HighlightColor::Error,
74                   DisableColors ? ColorMode::Disable : ColorMode::Auto)
75             .get()
76         << "error: ";
77}
78
79raw_ostream &WithColor::warning(raw_ostream &OS, StringRef Prefix,
80                                bool DisableColors) {
81  if (!Prefix.empty())
82    OS << Prefix << ": ";
83  return WithColor(OS, HighlightColor::Warning,
84                   DisableColors ? ColorMode::Disable : ColorMode::Auto)
85             .get()
86         << "warning: ";
87}
88
89raw_ostream &WithColor::note(raw_ostream &OS, StringRef Prefix,
90                             bool DisableColors) {
91  if (!Prefix.empty())
92    OS << Prefix << ": ";
93  return WithColor(OS, HighlightColor::Note,
94                   DisableColors ? ColorMode::Disable : ColorMode::Auto)
95             .get()
96         << "note: ";
97}
98
99raw_ostream &WithColor::remark(raw_ostream &OS, StringRef Prefix,
100                               bool DisableColors) {
101  if (!Prefix.empty())
102    OS << Prefix << ": ";
103  return WithColor(OS, HighlightColor::Remark,
104                   DisableColors ? ColorMode::Disable : ColorMode::Auto)
105             .get()
106         << "remark: ";
107}
108
109bool WithColor::colorsEnabled() {
110  switch (Mode) {
111  case ColorMode::Enable:
112    return true;
113  case ColorMode::Disable:
114    return false;
115  case ColorMode::Auto:
116    return UseColor == cl::BOU_UNSET ? OS.has_colors()
117                                     : UseColor == cl::BOU_TRUE;
118  }
119  llvm_unreachable("All cases handled above.");
120}
121
122WithColor &WithColor::changeColor(raw_ostream::Colors Color, bool Bold,
123                                  bool BG) {
124  if (colorsEnabled())
125    OS.changeColor(Color, Bold, BG);
126  return *this;
127}
128
129WithColor &WithColor::resetColor() {
130  if (colorsEnabled())
131    OS.resetColor();
132  return *this;
133}
134
135WithColor::~WithColor() { resetColor(); }
136
137void WithColor::defaultErrorHandler(Error Err) {
138  handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) {
139    WithColor::error() << Info.message() << '\n';
140  });
141}
142
143void WithColor::defaultWarningHandler(Error Warning) {
144  handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) {
145    WithColor::warning() << Info.message() << '\n';
146  });
147}
148