From 54c5bc511039de0d23c12e19c04ec353a2ff1b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 1 Aug 2025 15:12:30 +0800 Subject: [PATCH] Bar: refactor config to use nested objects and deprecates old fields --- doc/json_schema.json | 114 +++++++++++++++++++++++++++++++----------- src/common/option.c | 2 + src/common/percent.c | 20 ++++---- src/options/display.c | 109 ++++++++++++++++++++++++++++++---------- src/options/display.h | 6 +-- 5 files changed, 184 insertions(+), 67 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index b4c82c33e..3c6e5d5a7 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -997,50 +997,108 @@ "additionalProperties": false, "description": "Set the bar configuration", "properties": { + "char": { + "type": "object", + "additionalProperties": false, + "description": "Set the characters used in the bar", + "properties": { + "elapsed": { + "type": "string", + "description": "Set the character to use in elapsed part", + "default": "■" + }, + "total": { + "type": "string", + "description": "Set the character to use in total part", + "default": "-" + } + } + }, + "border": { + "oneOf": [ + { + "type": "null", + "description": "Disable bar borders" + }, + { + "type": "object", + "additionalProperties": false, + "description": "Set the string to use of borders of percentage bars", + "properties": { + "left": { + "type": "string", + "description": "Set the string to use at left border", + "default": "[ " + }, + "right": { + "type": "string", + "description": "Set the string to use at right border", + "default": " ]" + }, + "leftElapsed": { + "type": "string", + "description": "If both leftElapsed and rightElapsed are set, the border will be used as parts of bar content", + "default": "" + }, + "rightElapsed": { + "type": "string", + "description": "If both leftElapsed and rightElapsed are set, the border will be used as parts of bar content", + "default": "" + } + } + } + ] + }, + "color": { + "oneOf": [ + { + "type": "null", + "description": "Disable color in percentage bars" + }, + { + "type": "object", + "additionalProperties": false, + "description": "Set the color to use of percentage bars", + "properties": { + "elapsed": { + "description": "Color to use in the elapsed part of percentage bars\nBy default, auto selected by percent.color.{green,yellow,red}", + "$ref": "#/$defs/colors", + "default": "auto" + }, + "total": { + "description": "Color to use in the total part of percentage bars", + "$ref": "#/$defs/colors", + "default": "light_white" + }, + "border": { + "description": "Color to use in the borders of percentage bars", + "$ref": "#/$defs/colors", + "default": "light_white" + } + } + } + ] + }, "charElapsed": { "type": "string", - "description": "Set the character to use in elapsed part", + "description": "Set the character to use in elapsed part. Deprecated in v2.50.0", "default": "■" }, "charTotal": { "type": "string", - "description": "Set the character to use in total part", + "description": "Set the character to use in total part. Deprecated in v2.50.0", "default": "-" }, "borderLeft": { "type": "string", - "description": "Set the string to use at left border", + "description": "Set the string to use at left border. Deprecated in v2.50.0", "default": "[ " }, "borderRight": { "type": "string", - "description": "Set the string to use at right border", + "description": "Set the string to use at right border. Deprecated in v2.50.0", "default": " ]" }, - "borderLeftElapsed": { - "type": "string", - "description": "If both borderLeftElapsed and borderRightElapsed are set, the border will be used as parts of bar content", - "default": "" - }, - "borderRightElapsed": { - "type": "string", - "description": "If both borderLeftElapsed and borderRightElapsed are set, the border will be used as parts of bar content", - "default": "" - }, - "colorElapsed": { - "description": "Color to use in the elapsed part of percentage bars", - "$ref": "#/$defs/colors" - }, - "colorTotal": { - "description": "Color to use in the total part of percentage bars", - "$ref": "#/$defs/colors", - "default": "light_white" - }, - "colorBorder": { - "description": "Color to use in the borders of percentage bars", - "$ref": "#/$defs/colors", - "default": "light_white" - }, "width": { "type": "integer", "description": "Set the width of the bar, in number of characters", diff --git a/src/common/option.c b/src/common/option.c index f1af4b48b..f5e929e34 100644 --- a/src/common/option.c +++ b/src/common/option.c @@ -157,6 +157,8 @@ bool ffOptionParseBoolean(const char* str) void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer) { + if (value[0] == '\0') return; + // If value is already an ANSI escape code, use it if (value[0] == '\e' && value[1] == '[') { diff --git a/src/common/percent.c b/src/common/percent.c index 1d164db47..98c5acc64 100644 --- a/src/common/percent.c +++ b/src/common/percent.c @@ -67,14 +67,15 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf if(!borderAsValue && options->barBorderLeft.length) { - if(!options->pipe) + if(!options->pipe && options->barColorBorder.length > 0) ffStrbufAppendF(buffer, "\e[%sm", options->barColorBorder.chars); ffStrbufAppend(buffer, &options->barBorderLeft); } if (percent != percent) { - if(!options->pipe) + // No color config for NaN, use total color for simplification + if(!options->pipe && options->barColorTotal.length > 0) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m"); for (uint32_t i = 0; i < options->barWidth; ++i) @@ -93,16 +94,17 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf const char* colorRed = options->percentColorRed.chars; FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type; - bool monochrome = !!(percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT) || options->barColorElapsed.length; + + bool autoColorElapsed = ffStrbufIgnCaseEqualS(&options->barColorElapsed, "auto"); for (uint32_t i = 0; i < blocksPercent; ++i) { - if(!options->pipe) + if(!options->pipe && options->barColorElapsed.length > 0) { - if (monochrome) + if ((percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT) || !autoColorElapsed) { const char* color = NULL; - if (options->barColorElapsed.length) + if (!autoColorElapsed) color = options->barColorElapsed.chars; else if (green <= yellow) { @@ -139,7 +141,7 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf if (blocksPercent < options->barWidth) { - if(!options->pipe) + if(!options->pipe && options->barColorTotal.length > 0) ffStrbufAppendF(buffer, "\e[%sm", options->barColorTotal.chars); for (uint32_t i = blocksPercent; i < options->barWidth; ++i) { @@ -154,12 +156,12 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf if(!borderAsValue && options->barBorderRight.length) { - if(!options->pipe) + if(!options->pipe && options->barColorBorder.length > 0) ffStrbufAppendF(buffer, "\e[%sm", options->barColorBorder.chars); ffStrbufAppend(buffer, &options->barBorderRight); } - if(!options->pipe) + if(!options->pipe && (options->barColorElapsed.length > 0 || options->barColorTotal.length > 0 || options->barColorBorder.length > 0)) { ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); appendOutputColor(buffer, module); diff --git a/src/options/display.c b/src/options/display.c index 99adbf61c..8f21f1429 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -76,8 +76,6 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va } else if (ffStrEqualsIgnCase(key, "brightColor")) options->brightColor = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "binaryPrefix")) - return "`display.binaryPrefix` has been renamed to `display.size.binaryPrefix`. Sorry for another break change."; else if (ffStrEqualsIgnCase(key, "duration")) { if (!yyjson_is_obj(val)) @@ -265,38 +263,95 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va { if (yyjson_is_obj(val)) { - const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed")); - if (charElapsed) - ffStrbufSetS(&options->barCharElapsed, charElapsed); + yyjson_val* char_ = yyjson_obj_get(val, "char"); + if (char_) + { + if (!yyjson_is_obj(char_)) return "display.bar.char must be an object"; - const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal")); - if (charTotal) - ffStrbufSetS(&options->barCharTotal, charTotal); + const char* charElapsed = yyjson_get_str(yyjson_obj_get(char_, "elapsed")); + if (charElapsed) + ffStrbufSetS(&options->barCharElapsed, charElapsed); - yyjson_val* borderLeft = yyjson_obj_get(val, "borderLeft"); - if (borderLeft) - ffStrbufSetS(&options->barBorderLeft, yyjson_get_str(borderLeft)); + const char* charTotal = yyjson_get_str(yyjson_obj_get(char_, "total")); + if (charTotal) + ffStrbufSetS(&options->barCharTotal, charTotal); + } + else + { + const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed")); + if (charElapsed) + return "display.bar.charElapsed has been renamed to display.bar.char.elapsed."; - yyjson_val* borderRight = yyjson_obj_get(val, "borderRight"); - if (borderRight) - ffStrbufSetS(&options->barBorderRight, yyjson_get_str(borderRight)); + const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal")); + if (charTotal) + return "display.bar.charTotal has been renamed to display.bar.char.total."; + } - yyjson_val* borderLeftElapsed = yyjson_obj_get(val, "borderLeftElapsed"); - if (borderLeftElapsed) - ffStrbufSetS(&options->barBorderLeftElapsed, yyjson_get_str(borderLeftElapsed)); + yyjson_val* border = yyjson_obj_get(val, "border"); + if (border) + { + if (yyjson_is_null(border)) + { + ffStrbufClear(&options->barBorderLeft); + ffStrbufClear(&options->barBorderRight); + ffStrbufClear(&options->barBorderLeftElapsed); + ffStrbufClear(&options->barBorderRightElapsed); + } + else + { + if (!yyjson_is_obj(border)) return "display.bar.border must be an object"; - yyjson_val* borderRightElapsed = yyjson_obj_get(val, "borderRightElapsed"); - if (borderRightElapsed) - ffStrbufSetS(&options->barBorderRightElapsed, yyjson_get_str(borderRightElapsed)); + yyjson_val* borderLeft = yyjson_obj_get(border, "left"); + if (borderLeft) + ffStrbufSetS(&options->barBorderLeft, yyjson_get_str(borderLeft)); - yyjson_val* colorElapsed = yyjson_obj_get(val, "colorElapsed"); - if (colorElapsed) ffOptionParseColor(yyjson_get_str(colorElapsed), &options->barColorElapsed); + yyjson_val* borderRight = yyjson_obj_get(border, "right"); + if (borderRight) + ffStrbufSetS(&options->barBorderRight, yyjson_get_str(borderRight)); - yyjson_val* colorTotal = yyjson_obj_get(val, "colorTotal"); - if (colorTotal) ffOptionParseColor(yyjson_get_str(colorTotal), &options->barColorTotal); + yyjson_val* borderLeftElapsed = yyjson_obj_get(border, "leftElapsed"); + if (borderLeftElapsed) + ffStrbufSetS(&options->barBorderLeftElapsed, yyjson_get_str(borderLeftElapsed)); - yyjson_val* colorBorder = yyjson_obj_get(val, "colorBorder"); - if (colorBorder) ffOptionParseColor(yyjson_get_str(colorBorder), &options->barColorBorder); + yyjson_val* borderRightElapsed = yyjson_obj_get(border, "rightElapsed"); + if (borderRightElapsed) + ffStrbufSetS(&options->barBorderRightElapsed, yyjson_get_str(borderRightElapsed)); + } + } + else + { + yyjson_val* borderLeft = yyjson_obj_get(val, "borderLeft"); + if (borderLeft) + return "display.bar.borderLeft has been renamed to display.bar.border.left."; + + yyjson_val* borderRight = yyjson_obj_get(val, "borderRight"); + if (borderRight) + return "display.bar.borderRight has been renamed to display.bar.border.right."; + } + + yyjson_val* color = yyjson_obj_get(val, "color"); + if (color) + { + if (yyjson_is_null(color)) + { + ffStrbufClear(&options->barColorElapsed); + ffStrbufClear(&options->barColorTotal); + ffStrbufClear(&options->barColorBorder); + } + else + { + if (!yyjson_is_obj(color)) return "display.bar.color must be an object"; + + yyjson_val* colorElapsed = yyjson_obj_get(color, "elapsed"); + if (colorElapsed) ffOptionParseColor(yyjson_get_str(colorElapsed), &options->barColorElapsed); + + yyjson_val* colorTotal = yyjson_obj_get(color, "total"); + if (colorTotal) ffOptionParseColor(yyjson_get_str(colorTotal), &options->barColorTotal); + + yyjson_val* colorBorder = yyjson_obj_get(color, "border"); + if (colorBorder) ffOptionParseColor(yyjson_get_str(colorBorder), &options->barColorBorder); + } + } yyjson_val* width = yyjson_obj_get(val, "width"); if (width) @@ -720,7 +775,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->barBorderRight, " ]"); ffStrbufInit(&options->barBorderLeftElapsed); ffStrbufInit(&options->barBorderRightElapsed); - ffStrbufInit(&options->barColorElapsed); + ffStrbufInitStatic(&options->barColorElapsed, "auto"); ffStrbufInitStatic(&options->barColorTotal, instance.state.terminalLightTheme ? FF_COLOR_FG_WHITE : FF_COLOR_FG_LIGHT_WHITE); ffStrbufInitStatic(&options->barColorBorder, instance.state.terminalLightTheme ? FF_COLOR_FG_WHITE : FF_COLOR_FG_LIGHT_WHITE); options->barWidth = 10; diff --git a/src/options/display.h b/src/options/display.h index c1255f468..9fbe33d14 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -62,9 +62,9 @@ typedef struct FFOptionsDisplay FFstrbuf barBorderRight; FFstrbuf barBorderLeftElapsed; FFstrbuf barBorderRightElapsed; - FFstrbuf barColorElapsed; - FFstrbuf barColorTotal; - FFstrbuf barColorBorder; + FFstrbuf barColorElapsed; // "auto" for auto selection from percent config; empty for no custom color (inherits) + FFstrbuf barColorTotal; // empty for no custom color (inherits) + FFstrbuf barColorBorder; // empty for no custom color (inherits) uint8_t barWidth; FFPercentageTypeFlags percentType; uint8_t percentNdigits;