#include "fastfetch.h" #include "common/option.h" #include "common/color.h" #include "common/strutil.h" #include // Return start position of the inner key if the argument key belongs to the module specified, NULL otherwise const char* ffOptionTestPrefix(const char* argumentKey, const char* moduleName) { assert(argumentKey && moduleName); const char* subKey = argumentKey; if (!(subKey[0] == '-' && subKey[1] == '-')) { return NULL; } subKey += 2; uint32_t moduleNameLen = (uint32_t) strlen(moduleName); if (strncasecmp(subKey, moduleName, moduleNameLen) != 0) { return NULL; } subKey += moduleNameLen; if (subKey[0] == '\0') { return subKey; } if (subKey[0] != '-') { return NULL; } subKey += 1; return subKey; } void ffOptionParseString(const char* argumentKey, const char* value, FFstrbuf* buffer) { if (value == NULL) { fprintf(stderr, "Error: usage: %s \n", argumentKey); exit(477); } ffStrbufSetS(buffer, value); } uint32_t ffOptionParseUInt32(const char* argumentKey, const char* value) { if (value == NULL) { fprintf(stderr, "Error: usage: %s \n", argumentKey); exit(480); } char* end; unsigned long num = strtoul(value, &end, 10); if (value[0] == '-' || *end != '\0' || num > UINT32_MAX) { fprintf(stderr, "Error: usage: %s \n", argumentKey); exit(479); } return (uint32_t) num; } int32_t ffOptionParseInt32(const char* argumentKey, const char* value) { if (value == NULL) { fprintf(stderr, "Error: usage: %s \n", argumentKey); exit(480); } char* end; long num = strtol(value, &end, 10); if (*end != '\0' || num < INT32_MIN || num > INT32_MAX) { fprintf(stderr, "Error: usage: %s \n", argumentKey); exit(479); } return (int32_t) num; } int ffOptionParseEnum(const char* argumentKey, const char* requestedKey, FFKeyValuePair pairs[]) { if (requestedKey == NULL) { fprintf(stderr, "Error: usage: %s \n", argumentKey); exit(476); } for (const FFKeyValuePair* pPair = pairs; pPair->key; ++pPair) { if (ffStrEqualsIgnCase(requestedKey, pPair->key)) { return pPair->value; } } fprintf(stderr, "Error: unknown %s value: %s\n", argumentKey, requestedKey); exit(478); } bool ffOptionParseBoolean(const char* str) { return ( !ffStrSet(str) || ffStrEqualsIgnCase(str, "true") || ffStrEqualsIgnCase(str, "yes") || ffStrEqualsIgnCase(str, "on") || ffStrEqualsIgnCase(str, "1")); } void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer) { if (!value || value[0] == '\0') { return; } // If value is already an ANSI escape code, use it if (value[0] == '\e' && value[1] == '[') { ffStrbufAppendS(buffer, value + 2); ffStrbufTrimRight(buffer, 'm'); return; } ffStrbufEnsureFree(buffer, 63); while (*value != '\0') { #define FF_APPEND_COLOR_CODE_COND(prefix, code) \ if (ffStrStartsWithIgnCase(value, #prefix)) { \ ffStrbufAppendS(buffer, code); \ value += strlen(#prefix); \ continue; \ } #define FF_APPEND_COLOR_PROP_COND(prefix, prop) \ if (ffStrStartsWithIgnCase(value, #prefix)) { \ if (instance.config.display.prop.length) ffStrbufAppend(buffer, &instance.config.display.prop); \ else ffStrbufAppendS(buffer, FF_COLOR_FG_DEFAULT); \ value += strlen(#prefix); \ continue; \ } 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) else FF_APPEND_COLOR_CODE_COND(underline_, FF_COLOR_MODE_UNDERLINE) else FF_APPEND_COLOR_CODE_COND(blink_, FF_COLOR_MODE_BLINK) else FF_APPEND_COLOR_CODE_COND(inverse_, FF_COLOR_MODE_INVERSE) else FF_APPEND_COLOR_CODE_COND(hidden_, FF_COLOR_MODE_HIDDEN) else FF_APPEND_COLOR_CODE_COND(strike_, FF_COLOR_MODE_STRIKETHROUGH) else FF_APPEND_COLOR_CODE_COND(black, FF_COLOR_FG_BLACK) else FF_APPEND_COLOR_CODE_COND(red, FF_COLOR_FG_RED) else FF_APPEND_COLOR_CODE_COND(green, FF_COLOR_FG_GREEN) else FF_APPEND_COLOR_CODE_COND(yellow, FF_COLOR_FG_YELLOW) else FF_APPEND_COLOR_CODE_COND(blue, FF_COLOR_FG_BLUE) else FF_APPEND_COLOR_CODE_COND(magenta, FF_COLOR_FG_MAGENTA) else FF_APPEND_COLOR_CODE_COND(cyan, FF_COLOR_FG_CYAN) else FF_APPEND_COLOR_CODE_COND(white, FF_COLOR_FG_WHITE) else FF_APPEND_COLOR_CODE_COND(default, FF_COLOR_FG_DEFAULT) else FF_APPEND_COLOR_CODE_COND(light_black, FF_COLOR_FG_LIGHT_BLACK) else FF_APPEND_COLOR_CODE_COND(light_red, FF_COLOR_FG_LIGHT_RED) else FF_APPEND_COLOR_CODE_COND(light_green, FF_COLOR_FG_LIGHT_GREEN) else FF_APPEND_COLOR_CODE_COND(light_yellow, FF_COLOR_FG_LIGHT_YELLOW) else FF_APPEND_COLOR_CODE_COND(light_blue, FF_COLOR_FG_LIGHT_BLUE) else FF_APPEND_COLOR_CODE_COND(light_magenta, FF_COLOR_FG_LIGHT_MAGENTA) else FF_APPEND_COLOR_CODE_COND(light_cyan, FF_COLOR_FG_LIGHT_CYAN) else FF_APPEND_COLOR_CODE_COND(light_white, FF_COLOR_FG_LIGHT_WHITE) else FF_APPEND_COLOR_PROP_COND(keys, colorKeys) else FF_APPEND_COLOR_PROP_COND(title, colorTitle) else FF_APPEND_COLOR_PROP_COND(output, colorOutput) else FF_APPEND_COLOR_PROP_COND(separator, colorSeparator) else { fprintf(stderr, "Error: invalid color code found: %s\n", value); exit(479); } } else if (value[0] == '@') { // Xterm 256 color ++value; char* pend = NULL; uint32_t color = (uint32_t) strtoul(value, &pend, 10); if (pend == value || color > 255) { fprintf(stderr, "Error: invalid 256 color code found: %s\n", value); exit(479); } ffStrbufAppendS(buffer, FF_COLOR_FG_256); ffStrbufAppendUInt(buffer, color); value = pend; continue; } 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; #undef FF_APPEND_COLOR_CODE_COND #undef FF_APPEND_COLOR_PROP_COND } }