From cd2d1a04d8914f5e1797a487d035c89f4a76d481 Mon Sep 17 00:00:00 2001 From: Book-reader Date: Fri, 16 Jan 2026 10:26:18 +1300 Subject: [PATCH] Use a `Printable` struct for ansi rgb formatting instead of explicit allocations (#2696) * Use a `Printable` struct for ansi rgb formatting * update release notes * Some renaming. --------- Co-authored-by: Christoffer Lerno --- lib/std/core/ansi.c3 | 40 +++++++++++++++++++++++++++++++---- releasenotes.md | 1 + test/unit/stdlib/core/ansi.c3 | 7 +++--- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/lib/std/core/ansi.c3 b/lib/std/core/ansi.c3 index cedb703d4..68ffe7767 100644 --- a/lib/std/core/ansi.c3 +++ b/lib/std/core/ansi.c3 @@ -1,4 +1,5 @@ module std::core::string::ansi; +import std::io; enum Ansi : const inline String { @@ -56,6 +57,37 @@ enum Ansi : const inline String BG_BRIGHT_WHITE = "\e[107m", } +struct AnsiColor (Printable) +{ + char r, g, b; + bool bg; +} + +fn usz? AnsiColor.to_format(&self, Formatter* fmt) @dynamic +{ + return fmt.printf("\e[%s8;2;%s;%s;%sm", self.bg ? 4 : 3, self.r, self.g, self.b); +} + +<* + 24-bit color code + + @return `A struct that, when formatted with '%s', sets the foreground or background colour to the specified rgb value` +*> +fn AnsiColor get_color_rgb(char r, char g, char b, bool bg = false) +{ + return {r, g, b, bg}; +} + +<* + 24-bit color code + + @return `A struct that, when formatted with '%s', sets the foreground or background colour of printed text to the specified rgb value` +*> +fn AnsiColor get_color(uint rgb, bool bg = false) +{ + return {(char)(rgb >> 16), (char)((rgb & 0x00FF00) >> 8), (char)rgb, bg}; +} + <* 8-bit color code @@ -96,7 +128,7 @@ macro String color(uint $rgb, bool $bg = false) @const @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) +fn String make_color(Allocator mem, uint rgb, bool bg = false) @deprecated("use get_color instead") { return make_color_rgb(mem, (char)(rgb >> 16), (char)((rgb & 0xFF00) >> 8), (char)rgb, bg); } @@ -107,7 +139,7 @@ fn String make_color(Allocator mem, uint rgb, bool bg = false) @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) +fn String make_tcolor(uint rgb, bool bg = false) @deprecated("use get_color instead") { return make_color_rgb(tmem, (char)(rgb >> 16), (char)((rgb & 0xFF00) >> 8), (char)rgb, bg); } @@ -117,7 +149,7 @@ fn String make_tcolor(uint rgb, bool bg = false) @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) +fn String make_color_rgb(Allocator mem, char r, char g, char b, bool bg = false) @deprecated("use get_color_rgb instead") { return string::format(mem, "\e[%s8;2;%s;%s;%sm", bg ? 4 : 3, r, g, b); } @@ -127,7 +159,7 @@ fn String make_color_rgb(Allocator mem, char r, char g, char b, bool bg = false) @return `the string char for the given foreground color` *> -fn String make_tcolor_rgb(char r, char g, char b, bool bg = false) +fn String make_tcolor_rgb(char r, char g, char b, bool bg = false) @deprecated("use get_color_rgb instead") { return string::format(tmem, "\e[%s8;2;%s;%s;%sm", bg ? 4 : 3, r, g, b); } diff --git a/releasenotes.md b/releasenotes.md index 152f82523..68f053089 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -85,6 +85,7 @@ - Add `streebog` (aka "GOST-12") hashing with 256-bit and 512-bit outputs. #2659 - Add unit tests for HMAC 256 based on RFC 4231. #2743 - Add extra `AsciiCharset` constants and combine its related compile-time/runtime macros. #2688 +- Use a `Printable` struct for ansi RGB formatting instead of explicit allocation and deprecate the old method. ## 0.7.8 Change list diff --git a/test/unit/stdlib/core/ansi.c3 b/test/unit/stdlib/core/ansi.c3 index 8f36dda18..ffd9d3964 100644 --- a/test/unit/stdlib/core/ansi.c3 +++ b/test/unit/stdlib/core/ansi.c3 @@ -18,8 +18,9 @@ fn void test_color() test::eq("\u001B[48;2;255;204;255m", ansi::color(0xFFCCFF, true)); } -fn void test_make_color() +fn void test_get_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)); + test::eq("\u001B[38;2;255;204;254m", string::tformat("%s", ansi::get_color_rgb(0xFF, 0xCC, 0xFE))); + test::eq("\u001B[38;2;255;204;254m", string::tformat("%s", ansi::get_color(0xFFCCFE))); + test::eq("\u001B[48;2;255;204;254m", string::tformat("%s", ansi::get_color(0xFFCCFE, true))); }