1 //===---------------------AnsiTerminal.h ------------------------*- C++ -*-===// 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 #define ANSI_FG_COLOR_BLACK 30 10 #define ANSI_FG_COLOR_RED 31 11 #define ANSI_FG_COLOR_GREEN 32 12 #define ANSI_FG_COLOR_YELLOW 33 13 #define ANSI_FG_COLOR_BLUE 34 14 #define ANSI_FG_COLOR_PURPLE 35 15 #define ANSI_FG_COLOR_CYAN 36 16 #define ANSI_FG_COLOR_WHITE 37 17 18 #define ANSI_BG_COLOR_BLACK 40 19 #define ANSI_BG_COLOR_RED 41 20 #define ANSI_BG_COLOR_GREEN 42 21 #define ANSI_BG_COLOR_YELLOW 43 22 #define ANSI_BG_COLOR_BLUE 44 23 #define ANSI_BG_COLOR_PURPLE 45 24 #define ANSI_BG_COLOR_CYAN 46 25 #define ANSI_BG_COLOR_WHITE 47 26 27 #define ANSI_SPECIAL_FRAMED 51 28 #define ANSI_SPECIAL_ENCIRCLED 52 29 30 #define ANSI_CTRL_NORMAL 0 31 #define ANSI_CTRL_BOLD 1 32 #define ANSI_CTRL_FAINT 2 33 #define ANSI_CTRL_ITALIC 3 34 #define ANSI_CTRL_UNDERLINE 4 35 #define ANSI_CTRL_SLOW_BLINK 5 36 #define ANSI_CTRL_FAST_BLINK 6 37 #define ANSI_CTRL_IMAGE_NEGATIVE 7 38 #define ANSI_CTRL_CONCEAL 8 39 #define ANSI_CTRL_CROSSED_OUT 9 40 41 #define ANSI_ESC_START "\033[" 42 #define ANSI_ESC_END "m" 43 44 #define ANSI_STR(s) #s 45 #define ANSI_DEF_STR(s) ANSI_STR(s) 46 47 #define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END 48 49 #define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END 50 #define ANSI_2_CTRL(ctrl1, ctrl2) "\033["##ctrl1 ";"##ctrl2 ANSI_ESC_END 51 52 #include "llvm/ADT/ArrayRef.h" 53 #include "llvm/ADT/STLExtras.h" 54 #include "llvm/ADT/StringRef.h" 55 56 #include <string> 57 58 namespace lldb_private { 59 60 namespace ansi { 61 62 inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, 63 bool do_color = true) { 64 // Convert "${ansi.XXX}" tokens to ansi values or clear them if do_color is 65 // false. 66 static const struct { 67 const char *name; 68 const char *value; 69 } g_color_tokens[] = { 70 #define _TO_STR2(_val) #_val 71 #define _TO_STR(_val) _TO_STR2(_val) 72 {"fg.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END}, 73 {"fg.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END}, 74 {"fg.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END}, 75 {"fg.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END}, 76 {"fg.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END}, 77 {"fg.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END}, 78 {"fg.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END}, 79 {"fg.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END}, 80 {"bg.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END}, 81 {"bg.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END}, 82 {"bg.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END}, 83 {"bg.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END}, 84 {"bg.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END}, 85 {"bg.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END}, 86 {"bg.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END}, 87 {"bg.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END}, 88 {"normal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END}, 89 {"bold}", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END}, 90 {"faint}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END}, 91 {"italic}", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END}, 92 {"underline}", ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END}, 93 {"slow-blink}", 94 ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END}, 95 {"fast-blink}", 96 ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END}, 97 {"negative}", 98 ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END}, 99 {"conceal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END}, 100 {"crossed-out}", 101 ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END}, 102 #undef _TO_STR 103 #undef _TO_STR2 104 }; 105 auto codes = llvm::makeArrayRef(g_color_tokens); 106 107 static const char tok_hdr[] = "${ansi."; 108 109 std::string fmt; 110 while (!format.empty()) { 111 llvm::StringRef left, right; 112 std::tie(left, right) = format.split(tok_hdr); 113 114 fmt.append(left); 115 116 if (left == format && right.empty()) { 117 // The header was not found. Just exit. 118 break; 119 } 120 121 bool found_code = false; 122 for (const auto &code : codes) { 123 if (!right.consume_front(code.name)) 124 continue; 125 126 if (do_color) 127 fmt.append(code.value); 128 found_code = true; 129 break; 130 } 131 format = right; 132 // If we haven't found a valid replacement value, we just copy the string 133 // to the result without any modifications. 134 if (!found_code) 135 fmt.append(tok_hdr); 136 } 137 return fmt; 138 } 139 } 140 } // namespace lldb_private 141