1254721Semaste//===---------------------AnsiTerminal.h ------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9314564Sdim#define ANSI_FG_COLOR_BLACK 30
10314564Sdim#define ANSI_FG_COLOR_RED 31
11314564Sdim#define ANSI_FG_COLOR_GREEN 32
12314564Sdim#define ANSI_FG_COLOR_YELLOW 33
13314564Sdim#define ANSI_FG_COLOR_BLUE 34
14314564Sdim#define ANSI_FG_COLOR_PURPLE 35
15314564Sdim#define ANSI_FG_COLOR_CYAN 36
16314564Sdim#define ANSI_FG_COLOR_WHITE 37
17254721Semaste
18314564Sdim#define ANSI_BG_COLOR_BLACK 40
19314564Sdim#define ANSI_BG_COLOR_RED 41
20314564Sdim#define ANSI_BG_COLOR_GREEN 42
21314564Sdim#define ANSI_BG_COLOR_YELLOW 43
22314564Sdim#define ANSI_BG_COLOR_BLUE 44
23314564Sdim#define ANSI_BG_COLOR_PURPLE 45
24314564Sdim#define ANSI_BG_COLOR_CYAN 46
25314564Sdim#define ANSI_BG_COLOR_WHITE 47
26254721Semaste
27314564Sdim#define ANSI_SPECIAL_FRAMED 51
28314564Sdim#define ANSI_SPECIAL_ENCIRCLED 52
29254721Semaste
30314564Sdim#define ANSI_CTRL_NORMAL 0
31314564Sdim#define ANSI_CTRL_BOLD 1
32314564Sdim#define ANSI_CTRL_FAINT 2
33314564Sdim#define ANSI_CTRL_ITALIC 3
34314564Sdim#define ANSI_CTRL_UNDERLINE 4
35314564Sdim#define ANSI_CTRL_SLOW_BLINK 5
36314564Sdim#define ANSI_CTRL_FAST_BLINK 6
37314564Sdim#define ANSI_CTRL_IMAGE_NEGATIVE 7
38314564Sdim#define ANSI_CTRL_CONCEAL 8
39314564Sdim#define ANSI_CTRL_CROSSED_OUT 9
40254721Semaste
41314564Sdim#define ANSI_ESC_START "\033["
42314564Sdim#define ANSI_ESC_END "m"
43254721Semaste
44314564Sdim#define ANSI_STR(s) #s
45314564Sdim#define ANSI_DEF_STR(s) ANSI_STR(s)
46254721Semaste
47314564Sdim#define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END
48254721Semaste
49314564Sdim#define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END
50314564Sdim#define ANSI_2_CTRL(ctrl1, ctrl2) "\033["##ctrl1 ";"##ctrl2 ANSI_ESC_END
51296417Sdim
52341825Sdim#include "llvm/ADT/ArrayRef.h"
53314564Sdim#include "llvm/ADT/STLExtras.h"
54314564Sdim#include "llvm/ADT/StringRef.h"
55296417Sdim
56314564Sdim#include <string>
57254721Semaste
58360784Sdimnamespace lldb_private {
59254721Semaste
60314564Sdimnamespace ansi {
61254721Semaste
62314564Sdiminline std::string FormatAnsiTerminalCodes(llvm::StringRef format,
63314564Sdim                                           bool do_color = true) {
64314564Sdim  // Convert "${ansi.XXX}" tokens to ansi values or clear them if do_color is
65314564Sdim  // false.
66314564Sdim  static const struct {
67314564Sdim    const char *name;
68314564Sdim    const char *value;
69314564Sdim  } g_color_tokens[] = {
70314564Sdim#define _TO_STR2(_val) #_val
71314564Sdim#define _TO_STR(_val) _TO_STR2(_val)
72314564Sdim      {"fg.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END},
73314564Sdim      {"fg.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END},
74314564Sdim      {"fg.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END},
75314564Sdim      {"fg.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END},
76314564Sdim      {"fg.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END},
77314564Sdim      {"fg.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END},
78314564Sdim      {"fg.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END},
79314564Sdim      {"fg.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END},
80314564Sdim      {"bg.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END},
81314564Sdim      {"bg.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END},
82314564Sdim      {"bg.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END},
83314564Sdim      {"bg.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END},
84314564Sdim      {"bg.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END},
85314564Sdim      {"bg.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END},
86314564Sdim      {"bg.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END},
87314564Sdim      {"bg.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END},
88314564Sdim      {"normal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END},
89314564Sdim      {"bold}", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END},
90314564Sdim      {"faint}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END},
91314564Sdim      {"italic}", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END},
92314564Sdim      {"underline}", ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END},
93314564Sdim      {"slow-blink}",
94314564Sdim       ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END},
95314564Sdim      {"fast-blink}",
96314564Sdim       ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END},
97314564Sdim      {"negative}",
98314564Sdim       ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END},
99314564Sdim      {"conceal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END},
100314564Sdim      {"crossed-out}",
101314564Sdim       ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END},
102314564Sdim#undef _TO_STR
103314564Sdim#undef _TO_STR2
104314564Sdim  };
105314564Sdim  auto codes = llvm::makeArrayRef(g_color_tokens);
106254721Semaste
107314564Sdim  static const char tok_hdr[] = "${ansi.";
108254721Semaste
109314564Sdim  std::string fmt;
110314564Sdim  while (!format.empty()) {
111314564Sdim    llvm::StringRef left, right;
112314564Sdim    std::tie(left, right) = format.split(tok_hdr);
113254721Semaste
114314564Sdim    fmt.append(left);
115314564Sdim
116314564Sdim    if (left == format && right.empty()) {
117314564Sdim      // The header was not found.  Just exit.
118314564Sdim      break;
119254721Semaste    }
120314564Sdim
121341825Sdim    bool found_code = false;
122314564Sdim    for (const auto &code : codes) {
123314564Sdim      if (!right.consume_front(code.name))
124314564Sdim        continue;
125314564Sdim
126314564Sdim      if (do_color)
127314564Sdim        fmt.append(code.value);
128341825Sdim      found_code = true;
129314564Sdim      break;
130314564Sdim    }
131341825Sdim    format = right;
132341825Sdim    // If we haven't found a valid replacement value, we just copy the string
133341825Sdim    // to the result without any modifications.
134341825Sdim    if (!found_code)
135341825Sdim      fmt.append(tok_hdr);
136314564Sdim  }
137314564Sdim  return fmt;
138254721Semaste}
139314564Sdim}
140360784Sdim} // namespace lldb_private
141