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
17typedef 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
80should_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