From 17f4a6e0551751daa81e7aff1dd71c74c09a5e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 14 Feb 2024 22:07:08 +0800 Subject: [PATCH] Colors: support `block` related settings Fix #721 --- doc/json_schema.json | 23 ++++++++ src/data/help.json | 72 +++++++++++++++++++++-- src/fastfetch.c | 17 +++++- src/modules/colors/colors.c | 114 ++++++++++++++++++++++++++++++------ src/modules/colors/option.h | 7 +++ 5 files changed, 208 insertions(+), 25 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index ce10159d8..4236e1bbb 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1007,6 +1007,29 @@ "type": "integer", "minimum": 0, "default": 0 + }, + "block": { + "description": "Set behavior of block printing", + "type": "object", + "properties": { + "width": { + "description": "Set the block width in spaces", + "type": "integer", + "minimum": 1, + "default": 3 + }, + "range": { + "description": "Set the range of colors in the blocks to print", + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 15 + }, + "minItems": 2, + "maxItems": 2 + } + } } } }, diff --git a/src/data/help.json b/src/data/help.json index 9af1a17e6..172e081f8 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -122,7 +122,10 @@ { "long": "ds-force-drm", "desc": "Set if only DRM should be used to detect displays", - "remark": "Use this option if you encountered problems with other detection method. Linux only", + "remark": [ + "Use this option if you encountered problems with other detection method.", + "Linux only" + ], "arg": { "type": "enum", "optional": true, @@ -537,7 +540,13 @@ { "long": "percent-type", "desc": "Set the percentage output type", - "remark": "1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number", + "remark": [ + "1 for percentage number", + "2 for bar", + "3 for both", + "6 for bar only", + "9 for colored number" + ], "arg": { "type": "num", "default": 9 @@ -998,7 +1007,11 @@ { "long": "packages-winget", "desc": "Set if winget package count should be detected", - "remark": "This option is extremely slow. You may need to increase value of '--processing-timeout' to make it actually work", + "remark": [ + "This option is extremely slow.", + "You may need to increase value of '--processing-timeout' to make it actually work.", + "Windows only" + ], "arg": { "type": "bool", "optional": true, @@ -1052,7 +1065,10 @@ { "long": "battery-use-setup-api", "desc": "Set if \"SetupAPI\" should be used on Windows to detect battery info", - "remark": "SetupAPI supports multi batteries, but slower. Windows only", + "remark": [ + "SetupAPI supports multi batteries, but slower.", + "Windows only" + ], "arg": { "type": "bool", "optional": true, @@ -1088,7 +1104,10 @@ { "long": "de-slow-version-detection", "desc": "Set if DE version should be detected with slow operations", - "remark": "Usually is not necessary. Linux only", + "remark": [ + "It's only used as a fallback method. Please file a bug report if you encounter any issues.", + "Linux only" + ], "arg": { "type": "bool", "optional": true, @@ -1107,7 +1126,10 @@ { "long": "gpu-driver-specific", "desc": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)", - "remark": "Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported. Both require the latest proprietary driver to be installed", + "remark": [ + "Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported.", + "Both require the latest proprietary driver to be installed." + ], "arg": { "type": "bool", "optional": true, @@ -1342,6 +1364,44 @@ "type": "num", "default": 0 } + }, + { + "long": "colors-block-width", + "desc": "Set the block width in spaces", + "arg": { + "type": "num", + "default": 3 + } + }, + { + "long": "colors-block-range-start", + "desc": "Set the start range of colors in the blocks to print", + "remark": [ + "Display colors 0-15 in the blocks. (16 colors)", + "Display colors 0-7 in the blocks. (8 colors)", + "Only works for `--colors-symbol block`.", + "Must be in range 0-15", + "See also `--colors-range-end`" + ], + "arg": { + "type": "num", + "default": 0 + } + }, + { + "long": "colors-block-range-end", + "desc": "Set the end range of colors in the blocks to print", + "remark": [ + "Display colors 0-15 in the blocks. (16 colors)", + "Display colors 0-7 in the blocks. (8 colors)", + "Only works for `--colors-symbol block`.", + "Must be in range 0-15", + "See also `--colors-range-start`" + ], + "arg": { + "type": "num", + "default": 15 + } } ], "General module": [ diff --git a/src/fastfetch.c b/src/fastfetch.c index affd59aad..8b4f85b40 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -222,7 +222,22 @@ static bool printSpecificCommandHelp(const char* command) yyjson_val* remarkKey = yyjson_obj_get(flagObj, "remark"); if (remarkKey) - printf("%10s: %s\n", "Remark", yyjson_get_str(remarkKey)); + { + if (yyjson_is_str(remarkKey)) + printf("%10s: %s\n", "Remark", yyjson_get_str(remarkKey)); + else if (yyjson_is_arr(remarkKey) && yyjson_arr_size(remarkKey) > 0) + { + yyjson_val* remarkStr; + size_t remarkIdx, remarkMax; + yyjson_arr_foreach(remarkKey, remarkIdx, remarkMax, remarkStr) + { + if (remarkIdx == 0) + printf("%10s: %s\n", "Remark", yyjson_get_str(remarkStr)); + else + printf(" %s\n", yyjson_get_str(remarkStr)); + } + } + } return true; } diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ff144cbd8..e8bcacff4 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -4,6 +4,16 @@ #include "modules/colors/colors.h" #include "util/stringUtils.h" +static inline uint8_t min(uint8_t a, uint8_t b) +{ + return a < b ? a : b; +} + +static inline uint8_t max(uint8_t a, uint8_t b) +{ + return a > b ? a : b; +} + void ffPrintColors(FFColorsOptions* options) { if(instance.config.display.pipe) @@ -11,30 +21,36 @@ void ffPrintColors(FFColorsOptions* options) ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - if(options->paddingLeft > 0) - ffPrintCharTimes(' ', options->paddingLeft); + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(128); if (options->symbol == FF_COLORS_SYMBOL_BLOCK) { - // 4%d: Set the background color // 3%d: Set the foreground color - for(uint8_t i = 0; i < 8; i++) - printf("\033[3%dm███", i); + for(uint8_t i = options->block.range[0]; i <= min(options->block.range[1], 7); i++) + { + ffStrbufAppendF(&result, "\e[3%dm", i); + for (uint8_t j = 0; j < options->block.width; j++) + ffStrbufAppendS(&result, "█"); + } + if (result.length > 0) + { + if(options->paddingLeft > 0) + ffPrintCharTimes(' ', options->paddingLeft); - puts(FASTFETCH_TEXT_MODIFIER_RESET); - - ffLogoPrintLine(); - - if(options->paddingLeft > 0) - ffPrintCharTimes(' ', options->paddingLeft); + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); + ffStrbufPutTo(&result, stdout); + ffStrbufClear(&result); + ffLogoPrintLine(); + } // 1: Set everything to bolt. This causes normal colors on some systems to be bright. - // 4%d: Set the background to the not bright color - // 3%d: Set the foreground to the not bright color - // 10%d: Set the background to the bright color // 9%d: Set the foreground to the bright color - for(uint8_t i = 0; i < 8; i++) - printf("\033[1;3%d;9%dm███", i, i); + for(uint8_t i = max(options->block.range[0], 8); i <= options->block.range[1]; i++) + { + ffStrbufAppendF(&result, "\e[1;9%dm", i - 8); + for (uint8_t j = 0; j < options->block.width; j++) + ffStrbufAppendS(&result, "█"); + } } else { @@ -49,10 +65,16 @@ void ffPrintColors(FFColorsOptions* options) default: symbol = "███"; break; } for (int i = 8; i >= 1; --i) - printf("\e[3%dm%s ", i, symbol); + ffStrbufAppendF(&result, "\e[3%dm%s ", i, symbol); } - puts(FASTFETCH_TEXT_MODIFIER_RESET); + if (result.length > 0) + { + if(options->paddingLeft > 0) + ffPrintCharTimes(' ', options->paddingLeft); + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); + ffStrbufPutTo(&result, stdout); + } } bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, const char* value) @@ -82,6 +104,24 @@ bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, cons return true; } + if (ffStrEqualsIgnCase(subKey, "block-width")) + { + options->block.width = (uint8_t) ffOptionParseUInt32(key, value); + return true; + } + + if (ffStrEqualsIgnCase(subKey, "block-range-start")) + { + options->block.range[0] = min((uint8_t) ffOptionParseUInt32(key, value), 15); + return true; + } + + if (ffStrEqualsIgnCase(subKey, "block-range-end")) + { + options->block.range[1] = min((uint8_t) ffOptionParseUInt32(key, value), 15); + return true; + } + return false; } @@ -123,6 +163,40 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "block")) + { + if (!yyjson_is_obj(val)) + ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", key); + else + { + yyjson_val* width = yyjson_obj_get(val, "width"); + if (width) + options->block.width = (uint8_t) yyjson_get_uint(width); + + yyjson_val* range = yyjson_obj_get(val, "range"); + if (range) + { + if (!yyjson_is_arr(range) || yyjson_arr_size(range) != 2) + ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", key); + else + { + uint8_t start = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 0)); + uint8_t end = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 1)); + if (start > end) + ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", key); + else if (end > 15) + ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", key); + else + { + options->block.range[0] = start; + options->block.range[1] = end; + } + } + } + } + continue; + } + ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key); } } @@ -168,6 +242,10 @@ void ffInitColorsOptions(FFColorsOptions* options) ffStrbufSetStatic(&options->moduleArgs.key, " "); options->symbol = FF_COLORS_SYMBOL_BLOCK; options->paddingLeft = 0; + options->block = (FFBlockConfig) { + .width = 3, + .range = { 0, 15 }, + }; } void ffDestroyColorsOptions(FF_MAYBE_UNUSED FFColorsOptions* options) diff --git a/src/modules/colors/option.h b/src/modules/colors/option.h index e51cea6f1..24b93b7c7 100644 --- a/src/modules/colors/option.h +++ b/src/modules/colors/option.h @@ -14,6 +14,12 @@ typedef enum FFColorsSymbol FF_COLORS_SYMBOL_STAR, } FFColorsSymbol; +typedef struct FFBlockConfig +{ + uint8_t width; + uint8_t range[2]; +} FFBlockConfig; + typedef struct FFColorsOptions { FFModuleBaseInfo moduleInfo; @@ -21,4 +27,5 @@ typedef struct FFColorsOptions FFColorsSymbol symbol; uint32_t paddingLeft; + FFBlockConfig block; } FFColorsOptions;