diff --git a/lib/std/core/ansi.c3 b/lib/std/core/ansi.c3 new file mode 100644 index 000000000..cedb703d4 --- /dev/null +++ b/lib/std/core/ansi.c3 @@ -0,0 +1,133 @@ +module std::core::string::ansi; + +enum Ansi : const inline String +{ + RESET = "\e[0m", + BOLD = "\e[1m", + DIM = "\e[2m", + ITALIC = "\e[3m", + UNDERLINE = "\e[4m", + BLINK = "\e[5m", + BLINK_FAST = "\e[6m", + INVERT = "\e[7m", + HIDDEN = "\e[8m", + STRIKETHROUGH = "\e[9m", + DOUBLE_UNDER = "\e[21m", + NO_DIM = "\e[22m", + NO_ITALIC = "\e[23m", + NO_UNDERLINE = "\e[24m", + NO_BLINK = "\e[25m", + NO_INVERT = "\e[27m", + NO_HIDDEN = "\e[28m", + NO_STRIKETHROUGH = "\e[29m", + BLACK = "\e[30m", + RED = "\e[31m", + GREEN = "\e[32m", + YELLOW = "\e[33m", + BLUE = "\e[34m", + MAGENTA = "\e[35m", + CYAN = "\e[36m", + WHITE = "\e[37m", + DEFAULT = "\e[39m", + BRIGHT_BLACK = "\e[90m", + BRIGHT_RED = "\e[91m", + BRIGHT_GREEN = "\e[92m", + BRIGHT_YELLOW = "\e[93m", + BRIGHT_BLUE = "\e[94m", + BRIGHT_MAGENTA = "\e[95m", + BRIGHT_CYAN = "\e[96m", + BRIGHT_WHITE = "\e[97m", + BG_BLACK = "\e[40m", + BG_RED = "\e[41m", + BG_GREEN = "\e[42m", + BG_YELLOW = "\e[43m", + BG_BLUE = "\e[44m", + BG_MAGENTA = "\e[45m", + BG_CYAN = "\e[46m", + BG_WHITE = "\e[47m", + BG_DEFAULT = "\e[49m", + BG_BRIGHT_BLACK = "\e[100m", + BG_BRIGHT_RED = "\e[101m", + BG_BRIGHT_GREEN = "\e[102m", + BG_BRIGHT_YELLOW = "\e[103m", + BG_BRIGHT_BLUE = "\e[104m", + BG_BRIGHT_MAGENTA = "\e[105m", + BG_BRIGHT_CYAN = "\e[106m", + BG_BRIGHT_WHITE = "\e[107m", +} + +<* + 8-bit color code + + @return `the formatting char for the given background color` +*> +macro String color_8bit(char $index, bool $bg = false) @const +{ + int $mode = $bg ? 4 : 3; + return @sprintf("\e[%s8;5;%sm", $mode, $index); +} + +<* + 24-bit color code + + @return `the string for the given foreground color` +*> +macro String color_rgb(char $r, char $g, char $b, bool $bg = false) @const +{ + int $mode = $bg ? 4 : 3; + return @sprintf("\e[%s8;2;%s;%s;%sm", $mode, $r, $g, $b); +} + +<* + 24-bit color code rgb + + @require $rgb <= 0xFF_FF_FF : `Expected a 24 bit RGB value` + @return `the string char for the given foreground color` +*> +macro String color(uint $rgb, bool $bg = false) @const +{ + int $mode = $bg ? 4 : 3; + return @sprintf("\e[%s8;2;%s;%s;%sm", $mode, $rgb >> 16, ($rgb & 0xFF00) >> 8, $rgb & 0xFF); +} + +<* + 24-bit color code rgb + + @require rgb <= 0xFF_FF_FF : `Expected a 24 bit RGB value` + @return `the string char for the given foreground color` +*> +fn String make_color(Allocator mem, uint rgb, bool bg = false) +{ + return make_color_rgb(mem, (char)(rgb >> 16), (char)((rgb & 0xFF00) >> 8), (char)rgb, bg); +} + +<* + 24-bit color code rgb + + @require rgb <= 0xFF_FF_FF : `Expected a 24 bit RGB value` + @return `the string char for the given foreground color` +*> +fn String make_tcolor(uint rgb, bool bg = false) +{ + return make_color_rgb(tmem, (char)(rgb >> 16), (char)((rgb & 0xFF00) >> 8), (char)rgb, bg); +} + +<* + 24-bit color code rgb + + @return `the string char for the given foreground color` +*> +fn String make_color_rgb(Allocator mem, char r, char g, char b, bool bg = false) +{ + return string::format(mem, "\e[%s8;2;%s;%s;%sm", bg ? 4 : 3, r, g, b); +} + +<* + 24-bit color code rgb + + @return `the string char for the given foreground color` +*> +fn String make_tcolor_rgb(char r, char g, char b, bool bg = false) +{ + return string::format(tmem, "\e[%s8;2;%s;%s;%sm", bg ? 4 : 3, r, g, b); +} diff --git a/test/unit/stdlib/core/ansi.c3 b/test/unit/stdlib/core/ansi.c3 new file mode 100644 index 000000000..8f36dda18 --- /dev/null +++ b/test/unit/stdlib/core/ansi.c3 @@ -0,0 +1,25 @@ +module std::core::string::ansi @test; + +fn void test_color_8bit() +{ + test::eq("\u001B[38;5;255m", ansi::color_8bit(255)); + test::eq("\u001B[48;5;255m", ansi::color_8bit(255, true)); +} + +fn void test_color_rgb() +{ + test::eq("\u001B[38;2;255;204;255m", ansi::color_rgb(255, 204, 255)); + test::eq("\u001B[48;2;255;204;255m", ansi::color_rgb(255, 204, 255, true)); +} + +fn void test_color() +{ + test::eq("\u001B[38;2;255;204;255m", ansi::color(0xFFCCFF)); + test::eq("\u001B[48;2;255;204;255m", ansi::color(0xFFCCFF, true)); +} + +fn void test_make_color() +{ + test::eq("\u001B[38;2;255;204;255m", ansi::make_color(tmem, 0xFFCCFF)); + test::eq("\u001B[48;2;255;204;255m", ansi::make_color(tmem, 0xFFCCFF, true)); +}