Files
fastfetch/src/common/impl/option.c
T

186 lines
7.6 KiB
C
Raw Normal View History

#include "fastfetch.h"
2026-01-06 09:48:38 +08:00
#include "common/option.h"
#include "common/color.h"
2026-05-28 15:58:08 +08:00
#include "common/strutil.h"
2023-03-07 14:56:13 +08:00
2026-04-29 23:52:38 +08:00
#include <limits.h>
2023-03-07 14:56:13 +08:00
// Return start position of the inner key if the argument key belongs to the module specified, NULL otherwise
2026-03-29 09:28:49 +08:00
const char* ffOptionTestPrefix(const char* argumentKey, const char* moduleName) {
2026-04-29 23:52:38 +08:00
assert(argumentKey && moduleName);
2023-03-07 14:56:13 +08:00
const char* subKey = argumentKey;
2026-03-29 09:28:49 +08:00
if (!(subKey[0] == '-' && subKey[1] == '-')) {
2023-03-07 14:56:13 +08:00
return NULL;
2026-03-29 09:28:49 +08:00
}
2023-03-07 14:56:13 +08:00
subKey += 2;
2026-03-29 09:28:49 +08:00
uint32_t moduleNameLen = (uint32_t) strlen(moduleName);
if (strncasecmp(subKey, moduleName, moduleNameLen) != 0) {
2023-03-07 14:56:13 +08:00
return NULL;
2026-03-29 09:28:49 +08:00
}
2023-03-07 14:56:13 +08:00
subKey += moduleNameLen;
2026-03-29 09:28:49 +08:00
if (subKey[0] == '\0') {
return subKey;
2026-03-29 09:28:49 +08:00
}
2026-03-29 09:28:49 +08:00
if (subKey[0] != '-') {
2023-03-07 14:56:13 +08:00
return NULL;
2026-03-29 09:28:49 +08:00
}
2023-03-07 14:56:13 +08:00
subKey += 1;
return subKey;
}
2026-03-29 09:28:49 +08:00
void ffOptionParseString(const char* argumentKey, const char* value, FFstrbuf* buffer) {
if (value == NULL) {
2023-03-07 14:56:13 +08:00
fprintf(stderr, "Error: usage: %s <str>\n", argumentKey);
exit(477);
}
ffStrbufSetS(buffer, value);
}
2026-03-29 09:28:49 +08:00
uint32_t ffOptionParseUInt32(const char* argumentKey, const char* value) {
if (value == NULL) {
2023-03-07 14:56:13 +08:00
fprintf(stderr, "Error: usage: %s <num>\n", argumentKey);
exit(480);
}
char* end;
2026-04-29 23:52:38 +08:00
unsigned long num = strtoul(value, &end, 10);
if (value[0] == '-' || *end != '\0' || num > UINT32_MAX) {
2023-03-07 14:56:13 +08:00
fprintf(stderr, "Error: usage: %s <num>\n", argumentKey);
exit(479);
}
2026-04-29 23:52:38 +08:00
return (uint32_t) num;
2023-03-07 14:56:13 +08:00
}
2026-03-29 09:28:49 +08:00
int32_t ffOptionParseInt32(const char* argumentKey, const char* value) {
if (value == NULL) {
2023-06-25 14:33:13 +08:00
fprintf(stderr, "Error: usage: %s <num>\n", argumentKey);
exit(480);
}
char* end;
2026-04-29 23:52:38 +08:00
long num = strtol(value, &end, 10);
if (*end != '\0' || num < INT32_MIN || num > INT32_MAX) {
2023-06-25 14:33:13 +08:00
fprintf(stderr, "Error: usage: %s <num>\n", argumentKey);
exit(479);
}
2026-04-29 23:52:38 +08:00
return (int32_t) num;
2023-06-25 14:33:13 +08:00
}
2026-03-29 09:28:49 +08:00
int ffOptionParseEnum(const char* argumentKey, const char* requestedKey, FFKeyValuePair pairs[]) {
if (requestedKey == NULL) {
2023-03-07 14:56:13 +08:00
fprintf(stderr, "Error: usage: %s <value>\n", argumentKey);
exit(476);
}
2026-03-29 09:28:49 +08:00
for (const FFKeyValuePair* pPair = pairs; pPair->key; ++pPair) {
if (ffStrEqualsIgnCase(requestedKey, pPair->key)) {
2023-03-10 10:56:36 +08:00
return pPair->value;
2026-03-29 09:28:49 +08:00
}
2023-03-07 14:56:13 +08:00
}
fprintf(stderr, "Error: unknown %s value: %s\n", argumentKey, requestedKey);
exit(478);
}
2026-03-29 09:28:49 +08:00
bool ffOptionParseBoolean(const char* str) {
2023-03-07 16:13:53 +08:00
return (
!ffStrSet(str) ||
ffStrEqualsIgnCase(str, "true") ||
2026-03-29 09:28:49 +08:00
ffStrEqualsIgnCase(str, "yes") ||
ffStrEqualsIgnCase(str, "on") ||
ffStrEqualsIgnCase(str, "1"));
2023-03-07 16:13:53 +08:00
}
2026-03-29 09:28:49 +08:00
void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer) {
if (!value || value[0] == '\0') {
return;
}
// If value is already an ANSI escape code, use it
2026-03-29 09:28:49 +08:00
if (value[0] == '\e' && value[1] == '[') {
ffStrbufAppendS(buffer, value + 2);
ffStrbufTrimRight(buffer, 'm');
return;
}
ffStrbufEnsureFree(buffer, 63);
2026-03-29 09:28:49 +08:00
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; \
}
2024-05-28 15:38:45 +08:00
2026-03-29 09:28:49 +08:00
if (ffCharIsEnglishAlphabet(value[0])) {
2024-05-28 15:38:45 +08:00
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
2026-03-29 09:28:49 +08:00
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);
}
2026-03-29 09:28:49 +08:00
} else if (value[0] == '@') {
2026-01-08 10:42:58 +08:00
// 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;
2026-03-29 09:28:49 +08:00
} else if (value[0] == '#') {
2025-04-17 10:48:18 +08:00
// 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);
2026-03-29 09:28:49 +08:00
} else if (pend - value == 3) {
2025-04-17 10:48:18 +08:00
rgb = ((rgb & 0xF00) >> 8) * 0x110000 +
2026-03-29 09:28:49 +08:00
((rgb & 0x0F0) >> 4) * 0x001100 +
((rgb & 0x00F) >> 0) * 0x000011;
} else if (pend - value != 6) {
2025-04-17 10:48:18 +08:00
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;
}
2024-05-28 15:38:45 +08:00
ffStrbufAppendC(buffer, *value);
++value;
2026-03-29 09:28:49 +08:00
#undef FF_APPEND_COLOR_CODE_COND
#undef FF_APPEND_COLOR_PROP_COND
}
}