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