From 399e2235d4bd463a45bbbd1bc212a27beb389454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Oct 2023 10:26:15 +0800 Subject: [PATCH] Options (Display): split code --- CMakeLists.txt | 1 + src/common/bar.c | 44 ++-- src/common/commandoption.c | 10 +- src/common/init.c | 51 +---- src/common/jsonconfig.c | 147 +------------- src/common/jsonconfig.h | 1 - src/common/parsing.c | 8 +- src/common/printing.c | 22 +- src/fastfetch.c | 149 ++------------ src/fastfetch.h | 43 +--- src/logo/logo.c | 12 +- src/modules/battery/battery.c | 6 +- src/modules/brightness/brightness.c | 4 +- src/modules/colors/colors.c | 2 +- src/modules/cpuusage/cpuusage.c | 4 +- src/modules/disk/disk.c | 10 +- src/modules/memory/memory.c | 6 +- src/modules/swap/swap.c | 10 +- src/modules/title/title.c | 12 +- src/options/display.c | 298 ++++++++++++++++++++++++++++ src/options/display.h | 51 +++++ 21 files changed, 452 insertions(+), 439 deletions(-) create mode 100644 src/options/display.c create mode 100644 src/options/display.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 76aaf7612..67bab51bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,6 +354,7 @@ set(LIBFASTFETCH_SRC src/modules/wifi/wifi.c src/modules/wm/wm.c src/modules/wmtheme/wmtheme.c + src/options/display.c src/options/modules.c src/options/logo.c src/options/general.c diff --git a/src/common/bar.c b/src/common/bar.c index e250188d7..4bd6e76ba 100644 --- a/src/common/bar.c +++ b/src/common/bar.c @@ -6,15 +6,17 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t { assert(green <= 100 && yellow <= 100 && red <= 100); - uint32_t blocksPercent = (uint32_t) (percent / 100.0 * instance.config.barWidth + 0.5); - uint32_t blocksGreen = (uint32_t) (green / 100.0 * instance.config.barWidth + 0.5); - uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * instance.config.barWidth + 0.5); - uint32_t blocksRed = (uint32_t) (red / 100.0 * instance.config.barWidth + 0.5); - assert(blocksPercent <= instance.config.barWidth); + const FFOptionsDisplay* options = &instance.config.display; - if(instance.config.barBorder) + uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5); + uint32_t blocksGreen = (uint32_t) (green / 100.0 * options->barWidth + 0.5); + uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * options->barWidth + 0.5); + uint32_t blocksRed = (uint32_t) (red / 100.0 * options->barWidth + 0.5); + assert(blocksPercent <= options->barWidth); + + if(options->barBorder) { - if(!instance.config.pipe) + if(!options->pipe) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ "); else ffStrbufAppendS(buffer, "[ "); @@ -22,7 +24,7 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t for (uint32_t i = 0; i < blocksPercent; ++i) { - if(!instance.config.pipe) + if(!options->pipe) { if (i == blocksGreen) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m"); @@ -31,26 +33,26 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t else if (i == blocksRed) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m"); } - ffStrbufAppend(buffer, &instance.config.barCharElapsed); + ffStrbufAppend(buffer, &options->barCharElapsed); } - if (blocksPercent < instance.config.barWidth) + if (blocksPercent < options->barWidth) { - if(!instance.config.pipe) + if(!options->pipe) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m"); - for (uint32_t i = blocksPercent; i < instance.config.barWidth; ++i) - ffStrbufAppend(buffer, &instance.config.barCharTotal); + for (uint32_t i = blocksPercent; i < options->barWidth; ++i) + ffStrbufAppend(buffer, &options->barCharTotal); } - if(instance.config.barBorder) + if(options->barBorder) { - if(!instance.config.pipe) + if(!options->pipe) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]"); else ffStrbufAppendS(buffer, " ]"); } - if(!instance.config.pipe) + if(!options->pipe) ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); } @@ -67,12 +69,14 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t { assert(green <= 100 && yellow <= 100); - bool colored = !!(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT); + const FFOptionsDisplay* options = &instance.config.display; + + bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT); if (parentheses) ffStrbufAppendC(buffer, '('); - if (colored && !instance.config.pipe) + if (colored && !options->pipe) { if(green < yellow) { @@ -93,9 +97,9 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m"); } } - ffStrbufAppendF(buffer, "%.*f%%", instance.config.percentNdigits, percent); + ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent); - if (colored && !instance.config.pipe) + if (colored && !options->pipe) { ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); } diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 507393dc3..262675cba 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -131,12 +131,12 @@ void ffPrintCommandOption(FFdata* data) data->structure.chars[colonIndex] = '\0'; uint64_t ms = 0; - if(instance.config.stat) + if(instance.config.display.stat) ms = ffTimeGetTick(); parseStructureCommand(data->structure.chars + startIndex, &data->customValues); - if(instance.config.stat) + if(instance.config.display.stat) { ms = ffTimeGetTick() - ms; @@ -149,7 +149,7 @@ void ffPrintCommandOption(FFdata* data) { char str[32]; int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms); - if(instance.config.pipe) + if(instance.config.display.pipe) puts(str); else printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load @@ -157,7 +157,7 @@ void ffPrintCommandOption(FFdata* data) } #if defined(_WIN32) - if (!resultDoc && !instance.config.noBuffer) fflush(stdout); + if (!resultDoc && !instance.config.display.noBuffer) fflush(stdout); #endif startIndex = colonIndex + 1; @@ -169,7 +169,7 @@ void ffMigrateCommandOptionToJsonc(FFdata* data) //If we don't have a custom structure, use the default one if(data->structure.length == 0) ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); - instance.config.stat = false; + instance.config.display.stat = false; ffPrintCommandOption(data); yyjson_mut_write_fp(stdout, instance.state.migrateConfigDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL); } diff --git a/src/common/init.c b/src/common/init.c index 35e363a6c..8c5d4c7a2 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -33,38 +33,7 @@ static void defaultConfig(void) ffOptionsInitLogo(&instance.config.logo); ffOptionsInitGeneral(&instance.config.general); ffOptionsInitModules(&instance.config.modules); - - ffStrbufInit(&instance.config.colorKeys); - ffStrbufInit(&instance.config.colorTitle); - instance.config.brightColor = true; - ffStrbufInitStatic(&instance.config.keyValueSeparator, ": "); - - instance.config.showErrors = false; - instance.config.pipe = !isatty(STDOUT_FILENO); - - #ifdef NDEBUG - instance.config.disableLinewrap = !instance.config.pipe; - instance.config.hideCursor = !instance.config.pipe; - #else - instance.config.disableLinewrap = false; - instance.config.hideCursor = false; - #endif - - instance.config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC; - instance.config.sizeNdigits = 2; - instance.config.sizeMaxPrefix = UINT8_MAX; - instance.config.temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS; - instance.config.stat = false; - instance.config.noBuffer = false; - instance.config.keyWidth = 0; - - ffStrbufInitStatic(&instance.config.barCharElapsed, "■"); - ffStrbufInitStatic(&instance.config.barCharTotal, "-"); - instance.config.barWidth = 10; - instance.config.barBorder = true; - instance.config.percentType = 1; - instance.config.percentNdigits = 0; - + ffOptionsInitDisplay(&instance.config.display); ffOptionsInitLibrary(&instance.config.library); } @@ -144,11 +113,11 @@ void ffStart(void) startDetectionThreads(); #endif - ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe && !instance.state.resultDoc; - ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc; + ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc; + ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc; #ifdef _WIN32 - setvbuf(stdout, NULL, _IOFBF, instance.config.noBuffer ? 0 : 4096); + setvbuf(stdout, NULL, _IOFBF, instance.config.display.noBuffer ? 0 : 4096); SetConsoleCtrlHandler(consoleHandler, TRUE); HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode = 0; @@ -156,7 +125,7 @@ void ffStart(void) SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); SetConsoleOutputCP(CP_UTF8); #else - if (instance.config.noBuffer) setvbuf(stdout, NULL, _IONBF, 0); + if (instance.config.display.noBuffer) setvbuf(stdout, NULL, _IONBF, 0); struct sigaction action = { .sa_handler = exitSignalHandler }; sigaction(SIGINT, &action, NULL); sigaction(SIGTERM, &action, NULL); @@ -164,7 +133,7 @@ void ffStart(void) #endif //reset everything to default before we start printing - if(!instance.config.pipe && !instance.state.resultDoc) + if(!instance.config.display.pipe && !instance.state.resultDoc) fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); if(ffHideCursor) @@ -189,13 +158,7 @@ static void destroyConfig(void) ffOptionsDestroyLogo(&instance.config.logo); ffOptionsDestroyGeneral(&instance.config.general); ffOptionsDestroyModules(&instance.config.modules); - - ffStrbufDestroy(&instance.config.colorKeys); - ffStrbufDestroy(&instance.config.colorTitle); - ffStrbufDestroy(&instance.config.keyValueSeparator); - ffStrbufDestroy(&instance.config.barCharElapsed); - ffStrbufDestroy(&instance.config.barCharTotal); - + ffOptionsDestroyDisplay(&instance.config.display); ffOptionsDestroyLibrary(&instance.config.library); } diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 5a890ba22..1b32ed8b4 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -178,7 +178,7 @@ static const char* printJsonConfig(bool prepare) yyjson_arr_foreach(modules, idx, max, item) { uint64_t ms = 0; - if(!prepare && instance.config.stat) + if(!prepare && instance.config.display.stat) ms = ffTimeGetTick(); yyjson_val* module = item; @@ -200,7 +200,7 @@ static const char* printJsonConfig(bool prepare) else if(!parseModuleJsonObject(type, module)) return "Unknown module type"; - if(!prepare && instance.config.stat) + if(!prepare && instance.config.display.stat) { ms = ffTimeGetTick() - ms; if (resultDoc) @@ -212,7 +212,7 @@ static const char* printJsonConfig(bool prepare) { char str[32]; int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms); - if(instance.config.pipe) + if(instance.config.display.pipe) puts(str); else printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load @@ -220,152 +220,13 @@ static const char* printJsonConfig(bool prepare) } #if defined(_WIN32) - if (!instance.config.noBuffer && !resultDoc) fflush(stdout); + if (!instance.config.display.noBuffer && !resultDoc) fflush(stdout); #endif } return NULL; } -const char* ffParseDisplayJsonConfig(FFconfig* config) -{ - yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc); - assert(root); - - if (!yyjson_is_obj(root)) - return "Invalid JSON config format. Root value must be an object"; - - yyjson_val* object = yyjson_obj_get(root, "display"); - if (!object) return NULL; - if (!yyjson_is_obj(object)) return "Property 'display' must be an object"; - - yyjson_val *key_, *val; - size_t idx, max; - yyjson_obj_foreach(object, idx, max, key_, val) - { - const char* key = yyjson_get_str(key_); - - if (ffStrEqualsIgnCase(key, "stat")) - { - if ((config->stat = yyjson_get_bool(val))) - config->showErrors = true; - } - else if (ffStrEqualsIgnCase(key, "pipe")) - config->pipe = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "showErrors")) - config->showErrors = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "disableLinewrap")) - config->disableLinewrap = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "hideCursor")) - config->hideCursor = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "separator")) - ffStrbufSetS(&config->keyValueSeparator, yyjson_get_str(val)); - else if (ffStrEqualsIgnCase(key, "color")) - { - if (yyjson_is_str(val)) - { - ffOptionParseColor(yyjson_get_str(val), &config->colorKeys); - ffStrbufSet(&config->colorTitle, &config->colorKeys); - } - else if (yyjson_is_obj(val)) - { - const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys")); - if (colorKeys) - ffOptionParseColor(colorKeys, &config->colorKeys); - const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title")); - if (colorTitle) - ffOptionParseColor(colorTitle, &config->colorTitle); - } - else - return "display.color must be either a string or an object"; - } - else if (ffStrEqualsIgnCase(key, "brightColor")) - config->brightColor = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "binaryPrefix")) - { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "iec", FF_BINARY_PREFIX_TYPE_IEC }, - { "si", FF_BINARY_PREFIX_TYPE_SI }, - { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, - {}, - }); - if (error) return error; - config->binaryPrefixType = (FFBinaryPrefixType) value; - } - else if (ffStrEqualsIgnCase(key, "sizeNdigits")) - config->sizeNdigits = (uint8_t) yyjson_get_uint(val); - else if (ffStrEqualsIgnCase(key, "sizeMaxPrefix")) - { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "B", 0 }, - { "kB", 1 }, - { "MB", 2 }, - { "GB", 3 }, - { "TB", 4 }, - { "PB", 5 }, - { "EB", 6 }, - { "ZB", 7 }, - { "YB", 8 }, - {} - }); - if (error) return error; - config->sizeMaxPrefix = (uint8_t) value; - } - else if (ffStrEqualsIgnCase(key, "temperatureUnit")) - { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, - { "C", FF_TEMPERATURE_UNIT_CELSIUS }, - { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, - { "K", FF_TEMPERATURE_UNIT_KELVIN }, - {}, - }); - if (error) return error; - config->temperatureUnit = (FFTemperatureUnit) value; - } - else if (ffStrEqualsIgnCase(key, "percentType")) - config->percentType = (uint8_t) yyjson_get_uint(val); - else if (ffStrEqualsIgnCase(key, "percentNdigits")) - config->percentNdigits = (uint8_t) yyjson_get_uint(val); - else if (ffStrEqualsIgnCase(key, "bar")) - { - if (yyjson_is_obj(val)) - { - const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed")); - if (charElapsed) - ffStrbufSetS(&config->barCharElapsed, charElapsed); - - const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal")); - if (charTotal) - ffStrbufSetS(&config->barCharTotal, charTotal); - - yyjson_val* border = yyjson_obj_get(val, "border"); - if (border) - config->barBorder = yyjson_get_bool(border); - - yyjson_val* width = yyjson_obj_get(val, "width"); - if (width) - config->barWidth = (uint8_t) yyjson_get_uint(width); - } - else - return "display.bar must be an object"; - } - else if (ffStrEqualsIgnCase(key, "noBuffer")) - config->noBuffer = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "keyWidth")) - config->keyWidth = (uint32_t) yyjson_get_uint(val); - else - return "Unknown display property"; - } - - return NULL; -} - void ffPrintJsonConfig(bool prepare) { const char* error = printJsonConfig(prepare); diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index 2ca3fc950..08f522c5c 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -5,7 +5,6 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs); const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]); void ffPrintJsonConfig(bool prepare); -const char* ffParseDisplayJsonConfig(FFconfig* config); void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs); yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc, diff --git a/src/common/parsing.c b/src/common/parsing.c index 55a2780fe..5f5b18d04 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -65,7 +65,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha double size = (double) bytes; uint8_t counter = 0; - while(size >= base && counter < instance.config.sizeMaxPrefix && prefixes[counter + 1]) + while(size >= base && counter < instance.config.display.sizeMaxPrefix && prefixes[counter + 1]) { size /= base; counter++; @@ -74,12 +74,12 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha if(counter == 0) ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]); else - ffStrbufAppendF(result, "%.*f %s", instance.config.sizeNdigits, size, prefixes[counter]); + ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]); } void ffParseSize(uint64_t bytes, FFstrbuf* result) { - switch (instance.config.binaryPrefixType) + switch (instance.config.display.binaryPrefixType) { case FF_BINARY_PREFIX_TYPE_IEC: parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL}); @@ -98,7 +98,7 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result) void ffParseTemperature(double celsius, FFstrbuf* buffer) { - switch (instance.config.temperatureUnit) + switch (instance.config.display.temperatureUnit) { case FF_TEMPERATURE_UNIT_CELSIUS: ffStrbufAppendF(buffer, "%.1f°C", celsius); diff --git a/src/common/printing.c b/src/common/printing.c index b5a32175b..21df19cb3 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -14,16 +14,16 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " ")) return; - if(!instance.config.pipe) + if(!instance.config.display.pipe) { fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); - if (instance.config.brightColor) + if (instance.config.display.brightColor) fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); if(moduleArgs && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR) && moduleArgs->keyColor.length > 0) ffPrintColor(&moduleArgs->keyColor); else - ffPrintColor(&instance.config.colorKeys); + ffPrintColor(&instance.config.display.colorKeys); } //NULL check is required for modules with custom keys, e.g. disk with the folder path @@ -43,18 +43,18 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu ffStrbufWriteTo(&key, stdout); } - if(!instance.config.pipe) + if(!instance.config.display.pipe) fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); - ffStrbufWriteTo(&instance.config.keyValueSeparator, stdout); + ffStrbufWriteTo(&instance.config.display.keyValueSeparator, stdout); - if(!instance.config.pipe) + if(!instance.config.display.pipe) fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); - if (!instance.config.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH)) + if (!instance.config.display.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH)) { - uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.keyWidth; + uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.display.keyWidth; if (keyWidth > 0) printf("\e[%uG", (unsigned) (keyWidth + instance.state.logoWidth)); } @@ -77,17 +77,17 @@ void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFMo static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments) { - if(!instance.config.showErrors) + if(!instance.config.display.showErrors) return; ffPrintLogoAndKey(moduleName, moduleIndex, moduleArgs, printType); - if(!instance.config.pipe) + if(!instance.config.display.pipe) fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout); vprintf(message, arguments); - if(!instance.config.pipe) + if(!instance.config.display.pipe) fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); putchar('\n'); diff --git a/src/fastfetch.c b/src/fastfetch.c index 4a1cd470e..234d58e81 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -332,16 +332,6 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val exit(414); } -static inline void optionCheckString(const char* key, const char* value, FFstrbuf* buffer) -{ - if(value == NULL) - { - fprintf(stderr, "Error: usage: %s \n", key); - exit(477); - } - ffStrbufEnsureFree(buffer, 63); //This is not needed, as ffStrbufSetS will resize capacity if needed, but giving a higher start should improve performance -} - static void printVersion() { FFVersionResult result = {}; @@ -527,135 +517,20 @@ static void parseOption(FFdata* data, const char* key, const char* value) break; } } - - /////////////////// - //General options// - /////////////////// - - else if(ffOptionsParseGeneralCommandLine(&instance.config.general, key, value)) {} - - //////////////// - //Logo options// - //////////////// - - else if(ffOptionsParseLogoCommandLine(&instance.config.logo, key, value)) {} - - /////////////////// - //Display options// - /////////////////// - - else if(ffStrEqualsIgnCase(key, "--stat")) - { - if((instance.config.stat = ffOptionParseBoolean(value))) - instance.config.showErrors = true; - } - else if(ffStrEqualsIgnCase(key, "--pipe")) - instance.config.pipe = ffOptionParseBoolean(value); - else if(ffStrEqualsIgnCase(key, "--show-errors")) - instance.config.showErrors = ffOptionParseBoolean(value); - else if(ffStrEqualsIgnCase(key, "--disable-linewrap")) - instance.config.disableLinewrap = ffOptionParseBoolean(value); - else if(ffStrEqualsIgnCase(key, "--hide-cursor")) - instance.config.hideCursor = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "-s") || ffStrEqualsIgnCase(key, "--structure")) ffOptionParseString(key, value, &data->structure); - else if(ffStrEqualsIgnCase(key, "--separator")) - ffOptionParseString(key, value, &instance.config.keyValueSeparator); - else if(ffStrEqualsIgnCase(key, "--color")) - { - optionCheckString(key, value, &instance.config.colorKeys); - ffOptionParseColor(value, &instance.config.colorKeys); - ffStrbufSet(&instance.config.colorTitle, &instance.config.colorKeys); - } - else if(ffStrStartsWithIgnCase(key, "--color-")) - { - const char* subkey = key + strlen("--color-"); - if(ffStrEqualsIgnCase(subkey, "keys")) - { - optionCheckString(key, value, &instance.config.colorKeys); - ffOptionParseColor(value, &instance.config.colorKeys); - } - else if(ffStrEqualsIgnCase(subkey, "title")) - { - optionCheckString(key, value, &instance.config.colorTitle); - ffOptionParseColor(value, &instance.config.colorTitle); - } - else - goto error; - } - else if(ffStrEqualsIgnCase(key, "--key-width")) - instance.config.keyWidth = ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(key, "--bright-color")) - instance.config.brightColor = ffOptionParseBoolean(value); - else if(ffStrEqualsIgnCase(key, "--binary-prefix")) - { - instance.config.binaryPrefixType = (FFBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "iec", FF_BINARY_PREFIX_TYPE_IEC }, - { "si", FF_BINARY_PREFIX_TYPE_SI }, - { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, - {} - }); - } - else if(ffStrEqualsIgnCase(key, "--size-ndigits")) - instance.config.sizeNdigits = (uint8_t) ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(key, "--size-max-prefix")) - { - instance.config.sizeMaxPrefix = (uint8_t) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "B", 0 }, - { "kB", 1 }, - { "MB", 2 }, - { "GB", 3 }, - { "TB", 4 }, - { "PB", 5 }, - { "EB", 6 }, - { "ZB", 7 }, - { "YB", 8 }, - {} - }); - } - else if(ffStrEqualsIgnCase(key, "--temperature-unit")) - { - instance.config.temperatureUnit = (FFTemperatureUnit) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, - { "C", FF_TEMPERATURE_UNIT_CELSIUS }, - { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, - { "K", FF_TEMPERATURE_UNIT_KELVIN }, - {}, - }); - } - else if(ffStrEqualsIgnCase(key, "--percent-type")) - instance.config.percentType = (uint8_t) ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(key, "--percent-ndigits")) - instance.config.percentNdigits = (uint8_t) ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(key, "--no-buffer")) - instance.config.noBuffer = ffOptionParseBoolean(value); - else if(ffStrStartsWithIgnCase(key, "--bar-")) - { - const char* subkey = key + strlen("--bar-"); - if(ffStrEqualsIgnCase(subkey, "char-elapsed")) - ffOptionParseString(key, value, &instance.config.barCharElapsed); - else if(ffStrEqualsIgnCase(subkey, "char-total")) - ffOptionParseString(key, value, &instance.config.barCharTotal); - else if(ffStrEqualsIgnCase(subkey, "width")) - instance.config.barWidth = (uint8_t) ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(subkey, "border")) - instance.config.barBorder = ffOptionParseBoolean(value); - else - goto error; - } - /////////////////// - //Library options// - /////////////////// - else if(ffOptionsParseLibraryCommandLine(&instance.config.library, key, value)) {} + /////////// + //Options// + /////////// - /////////////////////// - //Module args options// - /////////////////////// - - else if(ffParseModuleOptions(key, value)) {} + else if( + ffOptionsParseGeneralCommandLine(&instance.config.general, key, value) || + ffOptionsParseLogoCommandLine(&instance.config.logo, key, value) || + ffOptionsParseDisplayCommandLine(&instance.config.display, key, value) || + ffOptionsParseLibraryCommandLine(&instance.config.library, key, value) || + ffParseModuleOptions(key, value) + ) {} ////////////////// //Unknown option// @@ -741,7 +616,7 @@ static void run(FFdata* data) error || (error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) || (error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) || - (error = ffParseDisplayJsonConfig(&instance.config)) || + (error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) || (error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) || false ) { @@ -760,7 +635,7 @@ static void run(FFdata* data) ffStart(); #if defined(_WIN32) - if (!instance.config.noBuffer) fflush(stdout); + if (!instance.config.display.noBuffer) fflush(stdout); #endif if (useJsonConfig) diff --git a/src/fastfetch.h b/src/fastfetch.h index 7be79ab60..e97e6c7bc 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -25,55 +25,16 @@ #include "options/modules.h" #include "options/logo.h" +#include "options/display.h" #include "options/general.h" #include "options/library.h" -typedef enum FFBinaryPrefixType -{ - FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) - FF_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ... - FF_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 K = 1 MB, ... -} FFBinaryPrefixType; - -typedef enum FFTemperatureUnit -{ - FF_TEMPERATURE_UNIT_CELSIUS, - FF_TEMPERATURE_UNIT_FAHRENHEIT, - FF_TEMPERATURE_UNIT_KELVIN, -} FFTemperatureUnit; - typedef struct FFconfig { FFOptionsLogo logo; + FFOptionsDisplay display; FFOptionsGeneral general; FFOptionsModules modules; - - //If one of those is empty, ffLogoPrint will set them - FFstrbuf colorKeys; - FFstrbuf colorTitle; - - bool brightColor; - - FFstrbuf keyValueSeparator; - - bool stat; - bool pipe; //disables logo and all escape sequences - bool showErrors; - bool disableLinewrap; - bool hideCursor; - FFBinaryPrefixType binaryPrefixType; - uint8_t sizeNdigits; - uint8_t sizeMaxPrefix; - FFTemperatureUnit temperatureUnit; - FFstrbuf barCharElapsed; - FFstrbuf barCharTotal; - uint8_t barWidth; - bool barBorder; - uint8_t percentType; - uint8_t percentNdigits; - bool noBuffer; - uint32_t keyWidth; - FFOptionsLibrary library; } FFconfig; diff --git a/src/logo/logo.c b/src/logo/logo.c index 582343fb7..7c4205a40 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -61,7 +61,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048); - if (instance.config.brightColor) + if (instance.config.display.brightColor) ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT); ffStrbufAppendNC(&result, options->paddingTop, '\n'); @@ -212,11 +212,11 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) static void logoApplyColors(const FFlogo* logo) { - if(instance.config.colorTitle.length == 0) - ffStrbufAppendS(&instance.config.colorTitle, logo->colorTitle ? logo->colorTitle : logo->colors[0]); + if(instance.config.display.colorTitle.length == 0) + ffStrbufAppendS(&instance.config.display.colorTitle, logo->colorTitle ? logo->colorTitle : logo->colors[0]); - if(instance.config.colorKeys.length == 0) - ffStrbufAppendS(&instance.config.colorKeys, logo->colorKeys ? logo->colorKeys : logo->colors[1]); + if(instance.config.display.colorKeys.length == 0) + ffStrbufAppendS(&instance.config.display.colorKeys, logo->colorKeys ? logo->colorKeys : logo->colors[1]); } static bool logoHasName(const FFlogo* logo, const FFstrbuf* name, bool small) @@ -462,7 +462,7 @@ void ffLogoPrint(void) //In pipe mode, we don't have a logo or padding. //We also don't need to set main color, because it won't be printed anyway. //So we can return quickly here. - if(instance.config.pipe || instance.state.resultDoc) + if(instance.config.display.pipe || instance.state.resultDoc) { instance.state.logoHeight = 0; instance.state.logoWidth = 0; diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 6a503cdc0..7318289fd 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -16,13 +16,13 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); bool showStatus = - !(instance.config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) && + !(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) && result->status.length > 0 && ffStrbufIgnCaseCompS(&result->status, "Unknown") != 0; if(result->capacity >= 0) { - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { if(result->capacity <= 20) ffAppendPercentBar(&str, result->capacity, 100, 100, 0); @@ -32,7 +32,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin ffAppendPercentBar(&str, result->capacity, 0, 100, 100); } - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if(str.length > 0) ffStrbufAppendC(&str, ' '); diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index df676f893..4bcabec82 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -50,12 +50,12 @@ void ffPrintBrightness(FFBrightnessOptions* options) FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); - if (instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffAppendPercentBar(&str, percent, 0, 100, 100); } - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if(str.length > 0) ffStrbufAppendC(&str, ' '); diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 9d6e65867..239e2ec8b 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -6,7 +6,7 @@ void ffPrintColors(FFColorsOptions* options) { - if(instance.config.pipe) + if(instance.config.display.pipe) return; ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 7583e30e3..7a059b1d5 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -47,9 +47,9 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (!options->separate) { - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) ffAppendPercentBar(&str, avgValue, 0, 50, 80); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if(str.length > 0) ffStrbufAppendC(&str, ' '); diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 1a1f4b2d8..b465d4845 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -15,7 +15,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) if(options->moduleArgs.key.length == 0) { - if(instance.config.pipe) + if(instance.config.display.pipe) ffStrbufAppendF(&key, "%s (%s)", FF_DISK_MODULE_NAME, disk->mountpoint.chars); else { @@ -57,16 +57,16 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) if(disk->bytesTotal > 0) { - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffAppendPercentBar(&str, bytesPercentage, 0, 50, 80); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { ffAppendPercentNum(&str, bytesPercentage, 50, 80, str.length > 0); ffStrbufAppendC(&str, ' '); @@ -75,7 +75,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) else ffStrbufAppendS(&str, "Unknown "); - if(!(instance.config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { if(disk->filesystem.length) ffStrbufAppendF(&str, "- %s ", disk->filesystem.chars); diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 12d8b1717..c3c00cbe6 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -38,16 +38,16 @@ void ffPrintMemory(FFMemoryOptions* options) { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffAppendPercentBar(&str, percentage, 0, 50, 80); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffAppendPercentNum(&str, percentage, 50, 80, str.length > 0); ffStrbufTrimRight(&str, ' '); diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 392002f10..25f9cf6a3 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -35,26 +35,26 @@ void ffPrintSwap(FFSwapOptions* options) FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (storage.bytesTotal == 0) { - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffAppendPercentBar(&str, 0, 0, 50, 80); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendS(&str, "Disabled"); } else { - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffAppendPercentBar(&str, percentage, 0, 50, 80); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffAppendPercentNum(&str, percentage, 50, 80, str.length > 0); } diff --git a/src/modules/title/title.c b/src/modules/title/title.c index fc37c3bc8..daad8413f 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -8,19 +8,19 @@ static void appendText(FFstrbuf* output, const FFstrbuf* text, const FFstrbuf* color) { - if (!instance.config.pipe) + if (!instance.config.display.pipe) { - if (instance.config.brightColor) + if (instance.config.display.brightColor) ffStrbufAppendS(output, FASTFETCH_TEXT_MODIFIER_BOLT); if (color->length > 0) ffStrbufAppendF(output, "\e[%sm", color->chars); - else if (instance.config.colorTitle.length > 0) - ffStrbufAppendF(output, "\e[%sm", instance.config.colorTitle.chars); + else if (instance.config.display.colorTitle.length > 0) + ffStrbufAppendF(output, "\e[%sm", instance.config.display.colorTitle.chars); } ffStrbufAppend(output, text); - if(!instance.config.pipe) + if(!instance.config.display.pipe) ffStrbufAppendS(output, FASTFETCH_TEXT_MODIFIER_RESET); } @@ -37,7 +37,7 @@ void ffPrintTitle(FFTitleOptions* options) appendText(&hostNameColored, &hostName, &options->colorHost); FF_STRBUF_AUTO_DESTROY atColored = ffStrbufCreate(); - if (!instance.config.pipe && options->colorAt.length > 0) + if (!instance.config.display.pipe && options->colorAt.length > 0) { ffStrbufAppendF(&atColored, "\e[%sm", options->colorAt.chars); ffStrbufAppendC(&atColored, '@'); diff --git a/src/options/display.c b/src/options/display.c new file mode 100644 index 000000000..5386d8b5c --- /dev/null +++ b/src/options/display.c @@ -0,0 +1,298 @@ +#include "fastfetch.h" +#include "common/jsonconfig.h" +#include "util/stringUtils.h" +#include "options/display.h" + +#include + +const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root) +{ + yyjson_val* object = yyjson_obj_get(root, "display"); + if (!object) return NULL; + if (!yyjson_is_obj(object)) return "Property 'display' must be an object"; + + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(object, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + + if (ffStrEqualsIgnCase(key, "stat")) + { + if ((options->stat = yyjson_get_bool(val))) + options->showErrors = true; + } + else if (ffStrEqualsIgnCase(key, "pipe")) + options->pipe = yyjson_get_bool(val); + else if (ffStrEqualsIgnCase(key, "showErrors")) + options->showErrors = yyjson_get_bool(val); + else if (ffStrEqualsIgnCase(key, "disableLinewrap")) + options->disableLinewrap = yyjson_get_bool(val); + else if (ffStrEqualsIgnCase(key, "hideCursor")) + options->hideCursor = yyjson_get_bool(val); + else if (ffStrEqualsIgnCase(key, "separator")) + ffStrbufSetS(&options->keyValueSeparator, yyjson_get_str(val)); + else if (ffStrEqualsIgnCase(key, "color")) + { + if (yyjson_is_str(val)) + { + ffOptionParseColor(yyjson_get_str(val), &options->colorKeys); + ffStrbufSet(&options->colorTitle, &options->colorKeys); + } + else if (yyjson_is_obj(val)) + { + const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys")); + if (colorKeys) + ffOptionParseColor(colorKeys, &options->colorKeys); + const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title")); + if (colorTitle) + ffOptionParseColor(colorTitle, &options->colorTitle); + } + else + return "display.color must be either a string or an object"; + } + else if (ffStrEqualsIgnCase(key, "brightColor")) + options->brightColor = yyjson_get_bool(val); + else if (ffStrEqualsIgnCase(key, "binaryPrefix")) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "iec", FF_BINARY_PREFIX_TYPE_IEC }, + { "si", FF_BINARY_PREFIX_TYPE_SI }, + { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, + {}, + }); + if (error) return error; + options->binaryPrefixType = (FFBinaryPrefixType) value; + } + else if (ffStrEqualsIgnCase(key, "sizeNdigits")) + options->sizeNdigits = (uint8_t) yyjson_get_uint(val); + else if (ffStrEqualsIgnCase(key, "sizeMaxPrefix")) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "B", 0 }, + { "kB", 1 }, + { "MB", 2 }, + { "GB", 3 }, + { "TB", 4 }, + { "PB", 5 }, + { "EB", 6 }, + { "ZB", 7 }, + { "YB", 8 }, + {} + }); + if (error) return error; + options->sizeMaxPrefix = (uint8_t) value; + } + else if (ffStrEqualsIgnCase(key, "temperatureUnit")) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, + { "C", FF_TEMPERATURE_UNIT_CELSIUS }, + { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, + { "K", FF_TEMPERATURE_UNIT_KELVIN }, + {}, + }); + if (error) return error; + options->temperatureUnit = (FFTemperatureUnit) value; + } + else if (ffStrEqualsIgnCase(key, "percentType")) + options->percentType = (uint8_t) yyjson_get_uint(val); + else if (ffStrEqualsIgnCase(key, "percentNdigits")) + options->percentNdigits = (uint8_t) yyjson_get_uint(val); + else if (ffStrEqualsIgnCase(key, "bar")) + { + if (yyjson_is_obj(val)) + { + const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed")); + if (charElapsed) + ffStrbufSetS(&options->barCharElapsed, charElapsed); + + const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal")); + if (charTotal) + ffStrbufSetS(&options->barCharTotal, charTotal); + + yyjson_val* border = yyjson_obj_get(val, "border"); + if (border) + options->barBorder = yyjson_get_bool(border); + + yyjson_val* width = yyjson_obj_get(val, "width"); + if (width) + options->barWidth = (uint8_t) yyjson_get_uint(width); + } + else + return "display.bar must be an object"; + } + else if (ffStrEqualsIgnCase(key, "noBuffer")) + options->noBuffer = yyjson_get_bool(val); + else if (ffStrEqualsIgnCase(key, "keyWidth")) + options->keyWidth = (uint32_t) yyjson_get_uint(val); + else + return "Unknown display property"; + } + + return NULL; +} + +static inline void optionCheckString(const char* key, const char* value, FFstrbuf* buffer) +{ + if(value == NULL) + { + fprintf(stderr, "Error: usage: %s \n", key); + exit(477); + } + ffStrbufEnsureFree(buffer, 63); //This is not needed, as ffStrbufSetS will resize capacity if needed, but giving a higher start should improve performance +} + +bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key, const char* value) +{ + if(ffStrEqualsIgnCase(key, "--stat")) + { + if((options->stat = ffOptionParseBoolean(value))) + options->showErrors = true; + } + else if(ffStrEqualsIgnCase(key, "--pipe")) + options->pipe = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(key, "--show-errors")) + options->showErrors = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(key, "--disable-linewrap")) + options->disableLinewrap = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(key, "--hide-cursor")) + options->hideCursor = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(key, "--separator")) + ffOptionParseString(key, value, &options->keyValueSeparator); + else if(ffStrEqualsIgnCase(key, "--color")) + { + optionCheckString(key, value, &options->colorKeys); + ffOptionParseColor(value, &options->colorKeys); + ffStrbufSet(&options->colorTitle, &options->colorKeys); + } + else if(ffStrStartsWithIgnCase(key, "--color-")) + { + const char* subkey = key + strlen("--color-"); + if(ffStrEqualsIgnCase(subkey, "keys")) + { + optionCheckString(key, value, &options->colorKeys); + ffOptionParseColor(value, &options->colorKeys); + } + else if(ffStrEqualsIgnCase(subkey, "title")) + { + optionCheckString(key, value, &options->colorTitle); + ffOptionParseColor(value, &options->colorTitle); + } + else + return false; + } + else if(ffStrEqualsIgnCase(key, "--key-width")) + options->keyWidth = ffOptionParseUInt32(key, value); + else if(ffStrEqualsIgnCase(key, "--bright-color")) + options->brightColor = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(key, "--binary-prefix")) + { + options->binaryPrefixType = (FFBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "iec", FF_BINARY_PREFIX_TYPE_IEC }, + { "si", FF_BINARY_PREFIX_TYPE_SI }, + { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, + {} + }); + } + else if(ffStrEqualsIgnCase(key, "--size-ndigits")) + options->sizeNdigits = (uint8_t) ffOptionParseUInt32(key, value); + else if(ffStrEqualsIgnCase(key, "--size-max-prefix")) + { + options->sizeMaxPrefix = (uint8_t) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "B", 0 }, + { "kB", 1 }, + { "MB", 2 }, + { "GB", 3 }, + { "TB", 4 }, + { "PB", 5 }, + { "EB", 6 }, + { "ZB", 7 }, + { "YB", 8 }, + {} + }); + } + else if(ffStrEqualsIgnCase(key, "--temperature-unit")) + { + options->temperatureUnit = (FFTemperatureUnit) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, + { "C", FF_TEMPERATURE_UNIT_CELSIUS }, + { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, + { "K", FF_TEMPERATURE_UNIT_KELVIN }, + {}, + }); + } + else if(ffStrEqualsIgnCase(key, "--percent-type")) + options->percentType = (uint8_t) ffOptionParseUInt32(key, value); + else if(ffStrEqualsIgnCase(key, "--percent-ndigits")) + options->percentNdigits = (uint8_t) ffOptionParseUInt32(key, value); + else if(ffStrEqualsIgnCase(key, "--no-buffer")) + options->noBuffer = ffOptionParseBoolean(value); + else if(ffStrStartsWithIgnCase(key, "--bar-")) + { + const char* subkey = key + strlen("--bar-"); + if(ffStrEqualsIgnCase(subkey, "char-elapsed")) + ffOptionParseString(key, value, &options->barCharElapsed); + else if(ffStrEqualsIgnCase(subkey, "char-total")) + ffOptionParseString(key, value, &options->barCharTotal); + else if(ffStrEqualsIgnCase(subkey, "width")) + options->barWidth = (uint8_t) ffOptionParseUInt32(key, value); + else if(ffStrEqualsIgnCase(subkey, "border")) + options->barBorder = ffOptionParseBoolean(value); + else + return false; + } + else + return false; + return true; +} + +void ffOptionsInitDisplay(FFOptionsDisplay* options) +{ + ffStrbufInit(&options->colorKeys); + ffStrbufInit(&options->colorTitle); + options->brightColor = true; + ffStrbufInitStatic(&options->keyValueSeparator, ": "); + + options->showErrors = false; + options->pipe = !isatty(STDOUT_FILENO); + + #ifdef NDEBUG + options->disableLinewrap = !options->pipe; + options->hideCursor = !options->pipe; + #else + options->disableLinewrap = false; + options->hideCursor = false; + #endif + + options->binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC; + options->sizeNdigits = 2; + options->sizeMaxPrefix = UINT8_MAX; + options->temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS; + options->stat = false; + options->noBuffer = false; + options->keyWidth = 0; + + ffStrbufInitStatic(&options->barCharElapsed, "■"); + ffStrbufInitStatic(&options->barCharTotal, "-"); + options->barWidth = 10; + options->barBorder = true; + options->percentType = 1; + options->percentNdigits = 0; +} + +void ffOptionsDestroyDisplay(FFOptionsDisplay* options) +{ + ffStrbufDestroy(&options->colorKeys); + ffStrbufDestroy(&options->colorTitle); + ffStrbufDestroy(&options->keyValueSeparator); + ffStrbufDestroy(&options->barCharElapsed); + ffStrbufDestroy(&options->barCharTotal); +} diff --git a/src/options/display.h b/src/options/display.h new file mode 100644 index 000000000..9bc9aee2b --- /dev/null +++ b/src/options/display.h @@ -0,0 +1,51 @@ +#pragma once + +#include "util/FFstrbuf.h" + +typedef enum FFBinaryPrefixType +{ + FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) + FF_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ... + FF_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 K = 1 MB, ... +} FFBinaryPrefixType; + +typedef enum FFTemperatureUnit +{ + FF_TEMPERATURE_UNIT_CELSIUS, + FF_TEMPERATURE_UNIT_FAHRENHEIT, + FF_TEMPERATURE_UNIT_KELVIN, +} FFTemperatureUnit; + +typedef struct FFOptionsDisplay +{ + //If one of those is empty, ffLogoPrint will set them + FFstrbuf colorKeys; + FFstrbuf colorTitle; + + bool brightColor; + + FFstrbuf keyValueSeparator; + + bool stat; + bool pipe; //disables logo and all escape sequences + bool showErrors; + bool disableLinewrap; + bool hideCursor; + FFBinaryPrefixType binaryPrefixType; + uint8_t sizeNdigits; + uint8_t sizeMaxPrefix; + FFTemperatureUnit temperatureUnit; + FFstrbuf barCharElapsed; + FFstrbuf barCharTotal; + uint8_t barWidth; + bool barBorder; + uint8_t percentType; + uint8_t percentNdigits; + bool noBuffer; + uint32_t keyWidth; +} FFOptionsDisplay; + +const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root); +bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key, const char* value); +void ffOptionsInitDisplay(FFOptionsDisplay* options); +void ffOptionsDestroyDisplay(FFOptionsDisplay* options);