Color: support #RGB and #RRGGBB

Fix #1694
This commit is contained in:
李通洲
2025-04-17 10:48:18 +08:00
parent 97c89c39d3
commit 29eaa35f4c
3 changed files with 103 additions and 0 deletions
+8
View File
@@ -1834,10 +1834,18 @@ if (BUILD_TESTS)
PRIVATE libfastfetch
)
add_executable(fastfetch-test-color
tests/color.c
)
target_link_libraries(fastfetch-test-color
PRIVATE libfastfetch
)
enable_testing()
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
add_test(NAME test-list COMMAND fastfetch-test-list)
add_test(NAME test-format COMMAND fastfetch-test-format)
add_test(NAME test-color COMMAND fastfetch-test-color)
endif()
##################
+30
View File
@@ -177,6 +177,7 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
if (ffCharIsEnglishAlphabet(value[0]))
{
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
else FF_APPEND_COLOR_CODE_COND(bold_, FF_COLOR_MODE_BOLD)
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
else FF_APPEND_COLOR_CODE_COND(dim_, FF_COLOR_MODE_DIM)
else FF_APPEND_COLOR_CODE_COND(italic_, FF_COLOR_MODE_ITALIC)
@@ -212,6 +213,35 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
exit(479);
}
}
else if (value[0] == '#')
{
// RGB color
++value;
char* pend = NULL;
uint32_t rgb = (uint32_t) strtoul(value, &pend, 16);
if (pend == value) {
fprintf(stderr, "Error: invalid RGB color code found: %s\n", value);
exit(479);
}
if (pend - value > 6) {
fprintf(stderr, "Error: RGB color code too long: %s\n", value);
exit(479);
}
else if (pend - value == 3) {
rgb = ((rgb & 0xF00) >> 8) * 0x110000 +
((rgb & 0x0F0) >> 4) * 0x001100 +
((rgb & 0x00F) >> 0) * 0x000011;
}
else if (pend - value != 6) {
fprintf(stderr, "Error: invalid RGB color code length: %s\n", value);
exit(479);
}
uint32_t r = rgb >> 16, g = (rgb >> 8) & 0xFF, b = rgb & 0xFF;
ffStrbufAppendF(buffer, FF_COLOR_FG_RGB "%u;%u;%u", r, g, b);
value = pend;
continue;
}
ffStrbufAppendC(buffer, *value);
++value;
+65
View File
@@ -0,0 +1,65 @@
#include "common/format.h"
#include "util/textModifier.h"
#include "fastfetch.h"
#include <stdlib.h>
static void verify(const char* color, const char* expected, int lineNo)
{
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
ffOptionParseColorNoClear(color, &result);
if (!ffStrbufEqualS(&result, expected))
{
fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %s: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, color, expected, result.chars);
exit(1);
}
}
#define VERIFY(color, expected) verify((color), (expected), __LINE__)
int main(void)
{
instance.config.display.pipe = true;
// Initialize dummy config colors for property tests
ffStrbufInitS(&instance.config.display.colorKeys, "94"); // light_blue
ffStrbufInitS(&instance.config.display.colorTitle, "95"); // light_magenta
{
VERIFY("", "");
VERIFY("1", "1");
VERIFY("red", "31");
VERIFY("light_green", "92");
VERIFY("default", "39");
VERIFY("blue", "34");
VERIFY("light_cyan", "96");
VERIFY("bold_red", "1;31");
VERIFY("dim_light_yellow", "2;93");
VERIFY("italic_underline_green", "3;4;32");
VERIFY("reset_blue", "0;34"); // Reset followed by color
VERIFY("#ff0000", "38;2;255;0;0"); // RRGGBB
VERIFY("#0f0", "38;2;0;255;0"); // RGB
VERIFY("#123456", "38;2;18;52;86");
VERIFY("#abc", "38;2;170;187;204");
VERIFY("bold_#ff00ff", "1;38;2;255;0;255");
VERIFY("underline_#123", "4;38;2;17;34;51");
VERIFY("\e[32m", "32"); // Direct ANSI code
VERIFY("\e[1;94m", "1;94"); // Direct ANSI code with mode
// Property colors (ensure dummy config colors are set)
VERIFY("keys", "94");
VERIFY("title", "95");
VERIFY("bold_keys", "1;94");
}
// Clean up dummy config colors
ffStrbufDestroy(&instance.config.display.colorKeys);
ffStrbufDestroy(&instance.config.display.colorTitle);
//Success
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
}