1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #pragma once |
4 | |
5 | #include <mos/mos_global.h> |
6 | #include <mos_string.h> |
7 | |
8 | /** |
9 | * @defgroup libs_ansicolors libs.AnsiColors |
10 | * @ingroup libs |
11 | * @brief ANSI color codes. |
12 | * @{ |
13 | */ |
14 | |
15 | #define STD_COLOR_LIGHT 0x8 |
16 | |
17 | typedef enum |
18 | { |
19 | Black = 0x0, |
20 | Blue = 0x1, |
21 | Green = 0x2, |
22 | Cyan = 0x3, |
23 | Red = 0x4, |
24 | Magenta = 0x5, |
25 | Brown = 0x6, |
26 | Gray = 0x7, |
27 | DarkGray = Black | STD_COLOR_LIGHT, |
28 | LightBlue = Blue | STD_COLOR_LIGHT, |
29 | LightGreen = Green | STD_COLOR_LIGHT, |
30 | LightCyan = Cyan | STD_COLOR_LIGHT, |
31 | LightRed = Red | STD_COLOR_LIGHT, |
32 | LightMagenta = Magenta | STD_COLOR_LIGHT, |
33 | Yellow = Brown | STD_COLOR_LIGHT, |
34 | White = Gray | STD_COLOR_LIGHT, |
35 | } standard_color_t; |
36 | |
37 | /** |
38 | * @brief ANSI color codes creator. |
39 | * |
40 | * @details |
41 | * Usage: |
42 | * - a foreground color: ANSI_COLOR(foreground) |
43 | * - a foreground color with style: ANSI_COLOR(foreground, style) |
44 | * - a foreground color with style and a background color: ANSI_COLOR(foreground, style, background) |
45 | */ |
46 | |
47 | // "_" is to prevent the "must specify at least one argument for '...' parameter of variadic macro" warning |
48 | #define ANSI_COLOR(...) "\033[" _ANSI_COLOR_N(__VA_ARGS__, _ANSI_COLOR_3, _ANSI_COLOR_2, _ANSI_COLOR_1, _)(__VA_ARGS__) "m" |
49 | #define ANSI_COLOR_RESET "\033[0m" |
50 | |
51 | // ! WARN: These below are not meant to be used directly |
52 | |
53 | #define _ANSI_FG "3" |
54 | #define _ANSI_BG "4" |
55 | |
56 | #define _ANSI_COLOR_black "0" |
57 | #define _ANSI_COLOR_red "1" |
58 | #define _ANSI_COLOR_green "2" |
59 | #define _ANSI_COLOR_yellow "3" |
60 | #define _ANSI_COLOR_blue "4" |
61 | #define _ANSI_COLOR_magenta "5" |
62 | #define _ANSI_COLOR_cyan "6" |
63 | #define _ANSI_COLOR_white "7" |
64 | |
65 | #define _ANSI_STYLE_regular "0" |
66 | #define _ANSI_STYLE_bright "1" |
67 | #define _ANSI_STYLE_faint "2" |
68 | #define _ANSI_STYLE_italic "3" |
69 | #define _ANSI_STYLE_underline "4" |
70 | #define _ANSI_STYLE_blink "5" |
71 | #define _ANSI_STYLE_blink_fast "6" // not widely supported |
72 | #define _ANSI_STYLE_reverse "7" |
73 | #define _ANSI_STYLE_invisible "8" |
74 | |
75 | #define _ANSI_COLOR_1(fg) _ANSI_FG _ANSI_COLOR_##fg |
76 | #define _ANSI_COLOR_2(fg, style) _ANSI_STYLE_##style ";" _ANSI_FG _ANSI_COLOR_##fg |
77 | #define _ANSI_COLOR_3(fg, style, bg) _ANSI_STYLE_##style ";" _ANSI_FG _ANSI_COLOR_##fg ";" _ANSI_BG _ANSI_COLOR_##bg |
78 | #define _ANSI_COLOR_N(_1, _2, _3, N, ...) N |
79 | |
80 | should_inline void get_ansi_color(char *buf, standard_color_t fg, standard_color_t bg) |
81 | { |
82 | MOS_UNUSED(bg); |
83 | static const char *g_ansi_colors[] = { |
84 | [Black] = ANSI_COLOR(black), |
85 | [Blue] = ANSI_COLOR(blue), |
86 | [Green] = ANSI_COLOR(green), |
87 | [Cyan] = ANSI_COLOR(cyan), |
88 | [Red] = ANSI_COLOR(red), |
89 | [Magenta] = ANSI_COLOR(magenta), |
90 | [Brown] = ANSI_COLOR(yellow), |
91 | [Gray] = ANSI_COLOR(white, bright), |
92 | [DarkGray] = ANSI_COLOR(white), |
93 | [LightBlue] = ANSI_COLOR(blue, bright), |
94 | [LightGreen] = ANSI_COLOR(green, bright), |
95 | [LightCyan] = ANSI_COLOR(cyan, bright), |
96 | [LightRed] = ANSI_COLOR(red, bright), |
97 | [LightMagenta] = ANSI_COLOR(magenta, bright), |
98 | [Yellow] = ANSI_COLOR(yellow, bright), |
99 | [White] = ANSI_COLOR(white, bright), |
100 | }; |
101 | |
102 | const char *color = g_ansi_colors[fg]; |
103 | |
104 | // TODO: add support for background colors |
105 | if (bg == Red) |
106 | color = ANSI_COLOR(red, blink); |
107 | |
108 | strcpy(dest: buf, src: color); |
109 | } |
110 | |
111 | /** @} */ |
112 | |