mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Global: move general options to a new separate folder
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# 2.2.0
|
||||
|
||||
Changes:
|
||||
* `--pipe` and `--stat` are moved from `general` options to `display` options. This affects cjson configuration.
|
||||
|
||||
Features:
|
||||
* Quirks for MIPS platforms (CPU, Linux)
|
||||
* Use devicetree path for OBP hosts (Host, Linux)
|
||||
|
||||
@@ -355,6 +355,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/wm/wm.c
|
||||
src/modules/wmtheme/wmtheme.c
|
||||
src/options/logo.c
|
||||
src/options/general.c
|
||||
src/util/edidHelper.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
|
||||
+10
-10
@@ -242,21 +242,11 @@
|
||||
"title": "Alias of multithreading",
|
||||
"default": true
|
||||
},
|
||||
"stat": {
|
||||
"type": "boolean",
|
||||
"title": "Show time usage (in ms) for individual modules",
|
||||
"default": false
|
||||
},
|
||||
"escapeBedrock": {
|
||||
"type": "boolean",
|
||||
"title": "On Bedrock Linux, whether to escape the bedrock jail",
|
||||
"default": true
|
||||
},
|
||||
"pipe": {
|
||||
"type": "boolean",
|
||||
"title": "Whether to enable pipe mode (disable logo and all escape sequences)",
|
||||
"default": false
|
||||
},
|
||||
"playerName": {
|
||||
"type": "string",
|
||||
"title": "The name of the player to use for module Media and Player. Linux only"
|
||||
@@ -287,6 +277,16 @@
|
||||
"title": "Configure how things to be displayed",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"stat": {
|
||||
"type": "boolean",
|
||||
"title": "Show time usage (in ms) for individual modules",
|
||||
"default": false
|
||||
},
|
||||
"pipe": {
|
||||
"type": "boolean",
|
||||
"title": "Whether to enable pipe mode (disable logo and all escape sequences)",
|
||||
"default": false
|
||||
},
|
||||
"showErrors": {
|
||||
"type": "boolean",
|
||||
"title": "Print occurring errors to the console. False to ignore errored modules",
|
||||
|
||||
@@ -87,7 +87,7 @@ void ffPrepareCommandOption(FFdata* data)
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
|
||||
ffPrepareNetIO(&instance.config.netIo);
|
||||
|
||||
if(instance.config.multithreading)
|
||||
if(instance.config.general.multithreading)
|
||||
{
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
|
||||
ffPreparePublicIp(&instance.config.publicIP);
|
||||
|
||||
+2
-18
@@ -33,23 +33,14 @@ static void initState(FFstate* state)
|
||||
static void defaultConfig(void)
|
||||
{
|
||||
ffInitLogoOptions(&instance.config.logo);
|
||||
ffInitGeneralOptions(&instance.config.general);
|
||||
|
||||
ffStrbufInit(&instance.config.colorKeys);
|
||||
ffStrbufInit(&instance.config.colorTitle);
|
||||
instance.config.brightColor = true;
|
||||
ffStrbufInitStatic(&instance.config.keyValueSeparator, ": ");
|
||||
instance.config.processingTimeout = 1000;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufInit(&instance.config.playerName);
|
||||
ffStrbufInit(&instance.config.osFile);
|
||||
instance.config.dsForceDrm = false;
|
||||
#elif defined(_WIN32)
|
||||
instance.config.wmiTimeout = 5000;
|
||||
#endif
|
||||
|
||||
instance.config.showErrors = false;
|
||||
instance.config.allowSlowOperations = false;
|
||||
instance.config.pipe = !isatty(STDOUT_FILENO);
|
||||
|
||||
#ifdef NDEBUG
|
||||
@@ -60,12 +51,10 @@ static void defaultConfig(void)
|
||||
instance.config.hideCursor = false;
|
||||
#endif
|
||||
|
||||
instance.config.escapeBedrock = true;
|
||||
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.multithreading = true;
|
||||
instance.config.stat = false;
|
||||
instance.config.noBuffer = false;
|
||||
instance.config.keyWidth = 0;
|
||||
@@ -233,7 +222,7 @@ static void exitSignalHandler(int signal)
|
||||
void ffStart(void)
|
||||
{
|
||||
#ifdef FF_START_DETECTION_THREADS
|
||||
if(instance.config.multithreading)
|
||||
if(instance.config.general.multithreading)
|
||||
startDetectionThreads();
|
||||
#endif
|
||||
|
||||
@@ -287,11 +276,6 @@ static void destroyConfig(void)
|
||||
ffStrbufDestroy(&instance.config.barCharElapsed);
|
||||
ffStrbufDestroy(&instance.config.barCharTotal);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufDestroy(&instance.config.playerName);
|
||||
ffStrbufDestroy(&instance.config.osFile);
|
||||
#endif
|
||||
|
||||
ffDestroyBatteryOptions(&instance.config.battery);
|
||||
ffDestroyBiosOptions(&instance.config.bios);
|
||||
ffDestroyBluetoothOptions(&instance.config.bluetooth);
|
||||
|
||||
+8
-54
@@ -227,59 +227,6 @@ static const char* printJsonConfig(bool prepare)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseGeneralJsonConfig(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, "general");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'general' 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, "allowSlowOperations"))
|
||||
config->allowSlowOperations = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
|
||||
config->multithreading = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "stat"))
|
||||
{
|
||||
if ((config->stat = yyjson_get_bool(val)))
|
||||
config->showErrors = true;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
|
||||
config->escapeBedrock = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "pipe"))
|
||||
config->pipe = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
|
||||
config->processingTimeout = (int32_t) yyjson_get_int(val);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
else if (ffStrEqualsIgnCase(key, "playerName"))
|
||||
ffStrbufSetS(&config->playerName, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osFile"))
|
||||
ffStrbufSetS(&config->osFile, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
|
||||
config->dsForceDrm = yyjson_get_bool(val);
|
||||
#elif defined(_WIN32)
|
||||
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
|
||||
config->wmiTimeout = (int32_t) yyjson_get_int(val);
|
||||
#endif
|
||||
|
||||
else
|
||||
return "Unknown general property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseDisplayJsonConfig(FFconfig* config)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
@@ -298,7 +245,14 @@ const char* ffParseDisplayJsonConfig(FFconfig* config)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "showErrors"))
|
||||
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);
|
||||
|
||||
@@ -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* ffParseGeneralJsonConfig(FFconfig* config);
|
||||
const char* ffParseDisplayJsonConfig(FFconfig* config);
|
||||
const char* ffParseLibraryJsonConfig(FFconfig* config);
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs);
|
||||
|
||||
@@ -48,7 +48,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
|
||||
int timeout = instance.config.processingTimeout;
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
if (timeout >= 0)
|
||||
fcntl(childPipeFd, F_SETFL, fcntl(childPipeFd, F_GETFL) | O_NONBLOCK);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ enum { FF_PIPE_BUFSIZ = 4096 };
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
{
|
||||
int timeout = instance.config.processingTimeout;
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
L"\\\\.\\pipe\\LOCAL\\",
|
||||
|
||||
@@ -32,7 +32,7 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
if(instance.config.allowSlowOperations)
|
||||
if(instance.config.general.allowSlowOperations)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
|
||||
@@ -67,7 +67,7 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
extern "C"
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
{
|
||||
if (instance.config.allowSlowOperations)
|
||||
if (instance.config.general.allowSlowOperations)
|
||||
return detectWithWmi(result);
|
||||
return detectWithRegistry(result);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
}
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
|
||||
if(instance.config.allowSlowOperations)
|
||||
if(instance.config.general.allowSlowOperations)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY name;
|
||||
ffStrbufInit(&name);
|
||||
|
||||
@@ -88,7 +88,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
|
||||
|
||||
if (!instance.config.dsForceDrm)
|
||||
if (!instance.config.general.dsForceDrm)
|
||||
{
|
||||
//We try wayland as our prefered display server, as it supports the most features.
|
||||
//This method can't detect the name of our WM / DE
|
||||
|
||||
@@ -154,7 +154,7 @@ static void getKDE(FFDisplayServerResult* result)
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
|
||||
{
|
||||
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"plasmashell",
|
||||
@@ -214,7 +214,7 @@ static void getMate(FFDisplayServerResult* result)
|
||||
|
||||
ffParseSemver(&result->deVersion, &major, &minor, µ);
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
|
||||
{
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"mate-session",
|
||||
@@ -250,7 +250,7 @@ static void getXFCE4(FFDisplayServerResult* result)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
|
||||
{
|
||||
//This is somewhat slow
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
@@ -276,7 +276,7 @@ static void getLXQt(FFDisplayServerResult* result)
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
|
||||
{
|
||||
//This is really, really, really slow. Thank you, LXQt developers
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
|
||||
@@ -161,8 +161,8 @@ static const char* getMedia(FFMediaResult* result)
|
||||
|
||||
// FIXME: This is shared for both player and media module.
|
||||
// However it uses an option in one specific module
|
||||
if(instance.config.playerName.length > 0)
|
||||
getCustomBus(&data, &instance.config.playerName, result);
|
||||
if(instance.config.general.playerName.length > 0)
|
||||
getCustomBus(&data, &instance.config.general.playerName, result);
|
||||
else
|
||||
getBestBus(&data, result);
|
||||
|
||||
|
||||
@@ -133,13 +133,13 @@ static void getDebianVersion(FFOSResult* result)
|
||||
|
||||
static void detectOS(FFOSResult* os)
|
||||
{
|
||||
if(instance.config.osFile.length > 0)
|
||||
if(instance.config.general.osFile.length > 0)
|
||||
{
|
||||
parseFile(instance.config.osFile.chars, os);
|
||||
parseFile(instance.config.general.osFile.chars, os);
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance.config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
|
||||
if(instance.config.general.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
|
||||
{
|
||||
if(os->id.length == 0)
|
||||
ffStrbufAppendS(&os->id, "bedrock");
|
||||
|
||||
@@ -110,6 +110,6 @@ void ffDetectPackagesImpl(FFPackagesResult* result)
|
||||
detectScoop(result);
|
||||
detectChoco(result);
|
||||
detectPacman(result);
|
||||
if (instance.config.allowSlowOperations)
|
||||
if (instance.config.general.allowSlowOperations)
|
||||
detectWinget(result);
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul
|
||||
{"font_size ", &fontSize},
|
||||
};
|
||||
|
||||
if(instance.config.allowSlowOperations)
|
||||
if(instance.config.general.allowSlowOperations)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
|
||||
if(!ffProcessAppendStdOut(&buf, (char* const[]){
|
||||
|
||||
@@ -119,7 +119,7 @@ static const char* detectVulkan(FFVulkanResult* result)
|
||||
|
||||
PFN_vkGetPhysicalDeviceMemoryProperties ffvkGetPhysicalDeviceMemoryProperties = NULL;
|
||||
PFN_vkGetPhysicalDeviceMemoryProperties2 ffvkGetPhysicalDeviceMemoryProperties2 =
|
||||
instance.config.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1
|
||||
instance.config.general.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1
|
||||
if(!ffvkGetPhysicalDeviceMemoryProperties2)
|
||||
ffvkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties");
|
||||
|
||||
|
||||
+22
-31
@@ -471,9 +471,9 @@ static void parseOption(FFdata* data, const char* key, const char* value)
|
||||
customValue->printKey = key[5] == '\0';
|
||||
}
|
||||
|
||||
///////////////////
|
||||
//General options//
|
||||
///////////////////
|
||||
////////////
|
||||
//Switches//
|
||||
////////////
|
||||
|
||||
else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--load-config") || ffStrEqualsIgnCase(key, "--config"))
|
||||
optionParseConfigFile(data, key, value);
|
||||
@@ -501,23 +501,8 @@ static void parseOption(FFdata* data, const char* key, const char* value)
|
||||
else
|
||||
instance.state.migrateConfigDoc = NULL;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "--thread") || ffStrEqualsIgnCase(key, "--multithreading"))
|
||||
instance.config.multithreading = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--stat"))
|
||||
{
|
||||
if((instance.config.stat = ffOptionParseBoolean(value)))
|
||||
instance.config.showErrors = true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "--allow-slow-operations"))
|
||||
instance.config.allowSlowOperations = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--escape-bedrock"))
|
||||
instance.config.escapeBedrock = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--pipe"))
|
||||
instance.config.pipe = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--load-user-config"))
|
||||
data->loadUserConfig = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--processing-timeout"))
|
||||
instance.config.processingTimeout = ffOptionParseInt32(key, value);
|
||||
else if(ffStrEqualsIgnCase(key, "--format"))
|
||||
{
|
||||
switch (ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
|
||||
@@ -543,17 +528,11 @@ static void parseOption(FFdata* data, const char* key, const char* value)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
else if(ffStrEqualsIgnCase(key, "--player-name"))
|
||||
ffOptionParseString(key, value, &instance.config.playerName);
|
||||
else if (ffStrEqualsIgnCase(key, "--os-file"))
|
||||
ffOptionParseString(key, value, &instance.config.osFile);
|
||||
else if(ffStrEqualsIgnCase(key, "--ds-force-drm"))
|
||||
instance.config.dsForceDrm = ffOptionParseBoolean(value);
|
||||
#elif defined(_WIN32)
|
||||
else if (ffStrEqualsIgnCase(key, "--wmi-timeout"))
|
||||
instance.config.wmiTimeout = ffOptionParseInt32(key, value);
|
||||
#endif
|
||||
///////////////////
|
||||
//General options//
|
||||
///////////////////
|
||||
|
||||
else if(ffParseGeneralCommandOptions(&instance.config.general, key, value)) {}
|
||||
|
||||
////////////////
|
||||
//Logo options//
|
||||
@@ -565,6 +544,13 @@ static void parseOption(FFdata* data, const char* key, const char* 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"))
|
||||
@@ -801,9 +787,14 @@ static void run(FFdata* data)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
if (!yyjson_is_obj(root))
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
if (
|
||||
(error = ffParseLogoJsonConfig(&instance.config.logo)) ||
|
||||
(error = ffParseGeneralJsonConfig(&instance.config)) ||
|
||||
error ||
|
||||
(error = ffParseLogoJsonConfig(&instance.config.logo, root)) ||
|
||||
(error = ffParseGeneralJsonConfig(&instance.config.general, root)) ||
|
||||
(error = ffParseDisplayJsonConfig(&instance.config)) ||
|
||||
(error = ffParseLibraryJsonConfig(&instance.config)) ||
|
||||
false
|
||||
|
||||
+4
-15
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "modules/options.h"
|
||||
#include "options/logo.h"
|
||||
#include "options/general.h"
|
||||
|
||||
typedef enum FFBinaryPrefixType
|
||||
{
|
||||
@@ -43,6 +44,7 @@ typedef enum FFTemperatureUnit
|
||||
typedef struct FFconfig
|
||||
{
|
||||
FFLogoOptions logo;
|
||||
FFGeneralOptions general;
|
||||
|
||||
//If one of those is empty, ffLogoPrint will set them
|
||||
FFstrbuf colorKeys;
|
||||
@@ -52,11 +54,11 @@ typedef struct FFconfig
|
||||
|
||||
FFstrbuf keyValueSeparator;
|
||||
|
||||
bool stat;
|
||||
bool pipe; //disables logo and all escape sequences
|
||||
bool showErrors;
|
||||
bool allowSlowOperations;
|
||||
bool disableLinewrap;
|
||||
bool hideCursor;
|
||||
bool escapeBedrock;
|
||||
FFBinaryPrefixType binaryPrefixType;
|
||||
uint8_t sizeNdigits;
|
||||
uint8_t sizeMaxPrefix;
|
||||
@@ -67,22 +69,9 @@ typedef struct FFconfig
|
||||
bool barBorder;
|
||||
uint8_t percentType;
|
||||
uint8_t percentNdigits;
|
||||
bool pipe; //disables logo and all escape sequences
|
||||
bool multithreading;
|
||||
bool stat;
|
||||
bool noBuffer;
|
||||
int32_t processingTimeout;
|
||||
uint32_t keyWidth;
|
||||
|
||||
// Module options that cannot be put in module option structure
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
FFstrbuf playerName;
|
||||
FFstrbuf osFile;
|
||||
bool dsForceDrm;
|
||||
#elif defined(_WIN32)
|
||||
int32_t wmiTimeout;
|
||||
#endif
|
||||
|
||||
FFBatteryOptions battery;
|
||||
FFBiosOptions bios;
|
||||
FFBluetoothOptions bluetooth;
|
||||
|
||||
@@ -1,560 +0,0 @@
|
||||
#include "logo/logo.h"
|
||||
|
||||
#include "common/jsonconfig.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
void ffInitLogoOptions(FFLogoOptions* options)
|
||||
{
|
||||
ffStrbufInit(&options->source);
|
||||
options->type = FF_LOGO_TYPE_AUTO;
|
||||
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
|
||||
ffStrbufInit(&options->colors[i]);
|
||||
options->width = 0;
|
||||
options->height = 0; //preserve aspect ratio
|
||||
options->paddingTop = 0;
|
||||
options->paddingLeft = 0;
|
||||
options->paddingRight = 4;
|
||||
options->printRemaining = true;
|
||||
options->preserveAspectRadio = false;
|
||||
options->recache = false;
|
||||
options->separate = false;
|
||||
|
||||
options->chafaFgOnly = false;
|
||||
ffStrbufInitStatic(&options->chafaSymbols, "block+border+space-wide-inverted"); // Chafa default
|
||||
options->chafaCanvasMode = UINT32_MAX;
|
||||
options->chafaColorSpace = UINT32_MAX;
|
||||
options->chafaDitherMode = UINT32_MAX;
|
||||
}
|
||||
|
||||
bool ffParseLogoCommandOptions(FFLogoOptions* options, const char* key, const char* value)
|
||||
{
|
||||
if (strcasecmp(key, "-l") == 0)
|
||||
goto logoType;
|
||||
|
||||
const char* subKey = ffOptionTestPrefix(key, "logo");
|
||||
if(subKey)
|
||||
{
|
||||
if (subKey[0] == '\0')
|
||||
{
|
||||
logoType:
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <none|small|logo-source>\n", key);
|
||||
exit(477);
|
||||
}
|
||||
//this is usually wanted when disabling logo
|
||||
if(strcasecmp(value, "none") == 0)
|
||||
{
|
||||
options->paddingTop = 0;
|
||||
options->paddingRight = 0;
|
||||
options->paddingLeft = 0;
|
||||
options->type = FF_LOGO_TYPE_NONE;
|
||||
}
|
||||
else if(strcasecmp(value, "small") == 0)
|
||||
{
|
||||
options->type = FF_LOGO_TYPE_SMALL;
|
||||
}
|
||||
else
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
}
|
||||
else if(strcasecmp(subKey, "type") == 0)
|
||||
{
|
||||
options->type = (FFLogoType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
|
||||
{ "auto", FF_LOGO_TYPE_AUTO },
|
||||
{ "builtin", FF_LOGO_TYPE_BUILTIN },
|
||||
{ "small", FF_LOGO_TYPE_SMALL },
|
||||
{ "file", FF_LOGO_TYPE_FILE },
|
||||
{ "file-raw", FF_LOGO_TYPE_FILE_RAW },
|
||||
{ "data", FF_LOGO_TYPE_DATA },
|
||||
{ "data-raw", FF_LOGO_TYPE_DATA_RAW },
|
||||
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
|
||||
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
|
||||
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
|
||||
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
|
||||
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
|
||||
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
|
||||
{ "none", FF_LOGO_TYPE_NONE },
|
||||
{},
|
||||
});
|
||||
}
|
||||
else if(ffStrStartsWithIgnCase(subKey, "color-") && subKey[6] != '\0' && subKey[7] == '\0') // matches "--logo-color-*"
|
||||
{
|
||||
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
|
||||
int index = (int)subKey[6] - '0' - 1;
|
||||
|
||||
//Match only --logo-color-[1-9]
|
||||
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
|
||||
{
|
||||
fprintf(stderr, "Error: invalid --color-[1-9] index: %c\n", key[13]);
|
||||
exit(472);
|
||||
}
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <str>\n", key);
|
||||
exit(477);
|
||||
}
|
||||
ffOptionParseColor(value, &options->colors[index]);
|
||||
}
|
||||
else if(strcasecmp(subKey, "width") == 0)
|
||||
options->width = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "height") == 0)
|
||||
options->height = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "padding") == 0)
|
||||
{
|
||||
uint32_t padding = ffOptionParseUInt32(key, value);
|
||||
options->paddingLeft = padding;
|
||||
options->paddingRight = padding;
|
||||
}
|
||||
else if(strcasecmp(subKey, "padding-top") == 0)
|
||||
options->paddingTop = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "padding-left") == 0)
|
||||
options->paddingLeft = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "padding-right") == 0)
|
||||
options->paddingRight = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "print-remaining") == 0)
|
||||
options->printRemaining = ffOptionParseBoolean(value);
|
||||
else if(strcasecmp(subKey, "preserve-aspect-radio") == 0)
|
||||
options->preserveAspectRadio = ffOptionParseBoolean(value);
|
||||
else if(strcasecmp(subKey, "recache") == 0)
|
||||
options->recache = ffOptionParseBoolean(value);
|
||||
else if(strcasecmp(subKey, "separate") == 0)
|
||||
options->separate = ffOptionParseBoolean(value);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if((subKey = ffOptionTestPrefix(key, "file")))
|
||||
{
|
||||
if(subKey[0] == '\0')
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_FILE;
|
||||
}
|
||||
else if(strcasecmp(subKey, "raw") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_FILE_RAW;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if((subKey = ffOptionTestPrefix(key, "data")))
|
||||
{
|
||||
if(subKey[0] == '\0')
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_DATA;
|
||||
}
|
||||
else if(strcasecmp(subKey, "raw") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_DATA_RAW;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if(strcasecmp(key, "--sixel") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_IMAGE_SIXEL;
|
||||
}
|
||||
else if(strcasecmp(key, "--kitty") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_IMAGE_KITTY;
|
||||
}
|
||||
else if(strcasecmp(key, "--kitty-direct") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_IMAGE_KITTY_DIRECT;
|
||||
}
|
||||
else if(strcasecmp(key, "--iterm") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_IMAGE_ITERM;
|
||||
}
|
||||
else if(strcasecmp(key, "--raw") == 0)
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_IMAGE_RAW;
|
||||
}
|
||||
else if((subKey = ffOptionTestPrefix(key, "chafa")))
|
||||
{
|
||||
if(subKey[0] == '\0')
|
||||
{
|
||||
ffOptionParseString(key, value, &options->source);
|
||||
options->type = FF_LOGO_TYPE_IMAGE_CHAFA;
|
||||
}
|
||||
else if(strcasecmp(subKey, "fg-only") == 0)
|
||||
options->chafaFgOnly = ffOptionParseBoolean(value);
|
||||
else if(strcasecmp(subKey, "symbols") == 0)
|
||||
ffOptionParseString(key, value, &options->chafaSymbols);
|
||||
else if(strcasecmp(subKey, "canvas-mode") == 0)
|
||||
options->chafaCanvasMode = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "color-space") == 0)
|
||||
options->chafaColorSpace = ffOptionParseUInt32(key, value);
|
||||
else if(strcasecmp(subKey, "dither-mode") == 0)
|
||||
options->chafaDitherMode = ffOptionParseUInt32(key, value);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffDestroyLogoOptions(FFLogoOptions* options)
|
||||
{
|
||||
ffStrbufDestroy(&options->source);
|
||||
ffStrbufDestroy(&options->chafaSymbols);
|
||||
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
|
||||
ffStrbufDestroy(&options->colors[i]);
|
||||
}
|
||||
|
||||
const char* ffParseLogoJsonConfig(FFLogoOptions* options)
|
||||
{
|
||||
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, "logo");
|
||||
if (!object) return NULL;
|
||||
if (yyjson_is_null(object))
|
||||
{
|
||||
options->type = FF_LOGO_TYPE_NONE;
|
||||
options->paddingTop = 0;
|
||||
options->paddingRight = 0;
|
||||
options->paddingLeft = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (yyjson_is_str(object))
|
||||
{
|
||||
const char* value = yyjson_get_str(object);
|
||||
ffStrbufSetS(&options->source, value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!yyjson_is_obj(object)) return "Property 'logo' 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 (strcasecmp(key, "type") == 0)
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "auto", FF_LOGO_TYPE_AUTO },
|
||||
{ "builtin", FF_LOGO_TYPE_BUILTIN },
|
||||
{ "small", FF_LOGO_TYPE_SMALL },
|
||||
{ "file", FF_LOGO_TYPE_FILE },
|
||||
{ "file-raw", FF_LOGO_TYPE_FILE_RAW },
|
||||
{ "data", FF_LOGO_TYPE_DATA },
|
||||
{ "data-raw", FF_LOGO_TYPE_DATA_RAW },
|
||||
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
|
||||
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
|
||||
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
|
||||
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
|
||||
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
|
||||
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
|
||||
{ "none", FF_LOGO_TYPE_NONE },
|
||||
{},
|
||||
});
|
||||
|
||||
if (error) return error;
|
||||
options->type = (FFLogoType) value;
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "source") == 0)
|
||||
{
|
||||
ffStrbufSetS(&options->source, yyjson_get_str(val));
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "color") == 0)
|
||||
{
|
||||
if (!yyjson_is_obj(val))
|
||||
return "Property 'color' must be an object";
|
||||
|
||||
yyjson_val *key_c, *valc;
|
||||
size_t idxc, maxc;
|
||||
yyjson_obj_foreach(val, idxc, maxc, key_c, valc)
|
||||
{
|
||||
const char* keyc = yyjson_get_str(key_c);
|
||||
uint32_t index = (uint32_t) strtoul(keyc, NULL, 10);
|
||||
if (index < 1 || index > FASTFETCH_LOGO_MAX_COLORS)
|
||||
return "Keys of property 'color' must be a number between 1 to 9";
|
||||
|
||||
ffOptionParseColor(yyjson_get_str(valc), &options->colors[index - 1]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "width") == 0)
|
||||
{
|
||||
uint32_t value = (uint32_t) yyjson_get_uint(val);
|
||||
if (value == 0)
|
||||
return "Logo width must be a possitive integer";
|
||||
options->width = value;
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "height") == 0)
|
||||
{
|
||||
uint32_t value = (uint32_t) yyjson_get_uint(val);
|
||||
if (value == 0)
|
||||
return "Logo height must be a possitive integer";
|
||||
options->height = value;
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "padding") == 0)
|
||||
{
|
||||
if (!yyjson_is_obj(val))
|
||||
return "Logo padding must be an object";
|
||||
|
||||
#define FF_PARSE_PADDING_POSITON(pos, paddingPos) \
|
||||
yyjson_val* pos = yyjson_obj_get(val, #pos); \
|
||||
if (pos) \
|
||||
{ \
|
||||
if (!yyjson_is_uint(pos)) \
|
||||
return "Logo padding values must be possitive integers"; \
|
||||
options->paddingPos = (uint32_t) yyjson_get_uint(pos); \
|
||||
}
|
||||
FF_PARSE_PADDING_POSITON(left, paddingLeft);
|
||||
FF_PARSE_PADDING_POSITON(top, paddingTop);
|
||||
FF_PARSE_PADDING_POSITON(right, paddingRight);
|
||||
#undef FF_PARSE_PADDING_POSITON
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "printRemaining") == 0)
|
||||
{
|
||||
options->printRemaining = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "preserveAspectRadio") == 0)
|
||||
{
|
||||
options->preserveAspectRadio = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "recache") == 0)
|
||||
{
|
||||
options->recache = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "separate") == 0)
|
||||
{
|
||||
options->separate = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
else if (strcasecmp(key, "chafa") == 0)
|
||||
{
|
||||
if (!yyjson_is_obj(val))
|
||||
return "Chafa config must be an object";
|
||||
|
||||
yyjson_val* fgOnly = yyjson_obj_get(val, "fgOnly");
|
||||
if (fgOnly)
|
||||
options->chafaFgOnly = yyjson_get_bool(fgOnly);
|
||||
|
||||
yyjson_val* symbols = yyjson_obj_get(val, "symbols");
|
||||
if (symbols)
|
||||
ffStrbufAppendS(&options->chafaSymbols, yyjson_get_str(symbols));
|
||||
|
||||
yyjson_val* canvasMode = yyjson_obj_get(val, "canvasMode");
|
||||
if (canvasMode)
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(canvasMode, &value, (FFKeyValuePair[]) {
|
||||
{ "TRUECOLOR", 0 },
|
||||
{ "INDEXED_256", 1 },
|
||||
{ "INDEXED_240", 2 },
|
||||
{ "INDEXED_16", 3 },
|
||||
{ "FGBG_BGFG", 4 },
|
||||
{ "FGBG", 5 },
|
||||
{ "INDEXED_8", 6 },
|
||||
{ "INDEXED_16_8", 7 },
|
||||
{},
|
||||
});
|
||||
|
||||
if (error) return error;
|
||||
options->chafaCanvasMode = (uint32_t) value;
|
||||
}
|
||||
|
||||
yyjson_val* colorSpace = yyjson_obj_get(val, "colorSpace");
|
||||
if (colorSpace)
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(colorSpace, &value, (FFKeyValuePair[]) {
|
||||
{ "RGB", 0 },
|
||||
{ "DIN99D", 1 },
|
||||
{},
|
||||
});
|
||||
|
||||
if (error) return error;
|
||||
options->chafaColorSpace = (uint32_t) value;
|
||||
}
|
||||
|
||||
yyjson_val* ditherMode = yyjson_obj_get(val, "ditherMode");
|
||||
if (ditherMode)
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(ditherMode, &value, (FFKeyValuePair[]) {
|
||||
{ "NONE", 0 },
|
||||
{ "ORDERED", 1 },
|
||||
{ "DIFFUSION", 2 },
|
||||
{},
|
||||
});
|
||||
|
||||
if (error) return error;
|
||||
options->chafaDitherMode = (uint32_t) value;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
return "Unknown logo key";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffGenerateLogoJsonConfig(FFLogoOptions* options, yyjson_mut_doc* doc)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyLogoOptions))) FFLogoOptions defaultOptions;
|
||||
ffInitLogoOptions(&defaultOptions);
|
||||
|
||||
yyjson_mut_val* obj = yyjson_mut_obj(doc);
|
||||
|
||||
if (options->type != defaultOptions.type)
|
||||
{
|
||||
switch (options->type)
|
||||
{
|
||||
case FF_LOGO_TYPE_NONE:
|
||||
yyjson_mut_obj_add_null(doc, doc->root, "logo");
|
||||
return;
|
||||
case FF_LOGO_TYPE_BUILTIN:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "builtin");
|
||||
break;
|
||||
case FF_LOGO_TYPE_SMALL:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "small");
|
||||
break;
|
||||
case FF_LOGO_TYPE_FILE:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "file");
|
||||
break;
|
||||
case FF_LOGO_TYPE_FILE_RAW:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "file-raw");
|
||||
break;
|
||||
case FF_LOGO_TYPE_DATA:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "data");
|
||||
break;
|
||||
case FF_LOGO_TYPE_DATA_RAW:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "data-raw");
|
||||
break;
|
||||
case FF_LOGO_TYPE_IMAGE_SIXEL:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "sixel");
|
||||
break;
|
||||
case FF_LOGO_TYPE_IMAGE_KITTY:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "kitty");
|
||||
break;
|
||||
case FF_LOGO_TYPE_IMAGE_ITERM:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "iterm");
|
||||
break;
|
||||
case FF_LOGO_TYPE_IMAGE_CHAFA:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "chafa");
|
||||
break;
|
||||
case FF_LOGO_TYPE_IMAGE_RAW:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "raw");
|
||||
break;
|
||||
default:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "auto");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ffStrbufEqual(&options->source, &defaultOptions.source))
|
||||
yyjson_mut_obj_add_str(doc, obj, "source", options->source.chars);
|
||||
|
||||
{
|
||||
yyjson_mut_val* color = yyjson_mut_arr(doc);
|
||||
for (int i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
|
||||
{
|
||||
if (!ffStrbufEqual(&options->colors[i], &defaultOptions.colors[i]))
|
||||
yyjson_mut_arr_add_strbuf(doc, color, &options->colors[i]);
|
||||
}
|
||||
if (yyjson_mut_arr_size(color) > 0)
|
||||
yyjson_mut_obj_add_val(doc, obj, "color", color);
|
||||
}
|
||||
|
||||
if (options->width != defaultOptions.width)
|
||||
yyjson_mut_obj_add_uint(doc, obj, "width", options->width);
|
||||
|
||||
if (options->height != defaultOptions.height)
|
||||
yyjson_mut_obj_add_uint(doc, obj, "height", options->height);
|
||||
|
||||
{
|
||||
yyjson_mut_val* padding = yyjson_mut_obj(doc);
|
||||
if (options->paddingTop != defaultOptions.paddingTop)
|
||||
yyjson_mut_obj_add_uint(doc, padding, "top", options->paddingTop);
|
||||
if (options->paddingLeft != defaultOptions.paddingLeft)
|
||||
yyjson_mut_obj_add_uint(doc, padding, "left", options->paddingLeft);
|
||||
if (options->paddingRight != defaultOptions.paddingRight)
|
||||
yyjson_mut_obj_add_uint(doc, padding, "right", options->paddingRight);
|
||||
|
||||
if (yyjson_mut_obj_size(padding) > 0)
|
||||
yyjson_mut_obj_add_val(doc, obj, "padding", padding);
|
||||
}
|
||||
|
||||
if (options->printRemaining != defaultOptions.printRemaining)
|
||||
yyjson_mut_obj_add_bool(doc, obj, "printRemaining", options->printRemaining);
|
||||
|
||||
if (options->preserveAspectRadio != defaultOptions.preserveAspectRadio)
|
||||
yyjson_mut_obj_add_bool(doc, obj, "preserveAspectRadio", options->preserveAspectRadio);
|
||||
|
||||
if (options->recache != defaultOptions.recache)
|
||||
yyjson_mut_obj_add_bool(doc, obj, "recache", options->recache);
|
||||
|
||||
if (options->separate != defaultOptions.separate)
|
||||
yyjson_mut_obj_add_bool(doc, obj, "separate", options->separate);
|
||||
|
||||
{
|
||||
yyjson_mut_val* chafa = yyjson_mut_obj(doc);
|
||||
if (options->chafaFgOnly != defaultOptions.chafaFgOnly)
|
||||
yyjson_mut_obj_add_bool(doc, chafa, "fgOnly", options->chafaFgOnly);
|
||||
if (!ffStrbufEqual(&options->chafaSymbols, &defaultOptions.chafaSymbols))
|
||||
yyjson_mut_obj_add_strbuf(doc, chafa, "symbols", &options->chafaSymbols);
|
||||
if (options->chafaCanvasMode != defaultOptions.chafaCanvasMode && options->chafaCanvasMode <= 7)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, chafa, "canvasMode", ((const char* []) {
|
||||
"TRUECOLOR",
|
||||
"INDEXED_256",
|
||||
"INDEXED_240",
|
||||
"INDEXED_16",
|
||||
"FGBG_BGFG",
|
||||
"FGBG",
|
||||
"INDEXED_8",
|
||||
"INDEXED_16_8",
|
||||
})[options->chafaCanvasMode]);
|
||||
}
|
||||
if (options->chafaColorSpace != defaultOptions.chafaColorSpace && options->chafaColorSpace <= 1)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, chafa, "colorSpace", ((const char* []) {
|
||||
"RGB",
|
||||
"DIN99D",
|
||||
})[options->chafaColorSpace]);
|
||||
}
|
||||
if (options->chafaDitherMode != defaultOptions.chafaDitherMode && options->chafaDitherMode <= 2)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, chafa, "ditherMode", ((const char* []) {
|
||||
"NONE",
|
||||
"ORDERED",
|
||||
"DIFFUSION",
|
||||
})[options->chafaDitherMode]);
|
||||
}
|
||||
|
||||
if (yyjson_mut_obj_size(chafa) > 0)
|
||||
yyjson_mut_obj_add_val(doc, obj, "chafa", chafa);
|
||||
}
|
||||
|
||||
if (yyjson_mut_obj_size(obj) > 0)
|
||||
yyjson_mut_obj_add_val(doc, doc->root, "logo", obj);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
#define FASTFETCH_LOGO_MAX_NAMES 9
|
||||
#define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9)
|
||||
|
||||
typedef enum FFLogoType
|
||||
{
|
||||
FF_LOGO_TYPE_AUTO, //if something is given, first try builtin, then file. Otherwise detect logo
|
||||
FF_LOGO_TYPE_BUILTIN, //builtin ascii art
|
||||
FF_LOGO_TYPE_SMALL, //builtin ascii art, small version
|
||||
FF_LOGO_TYPE_FILE, //text file, printed with color code replacement
|
||||
FF_LOGO_TYPE_FILE_RAW, //text file, printed as is
|
||||
FF_LOGO_TYPE_DATA, //text data, printed with color code replacement
|
||||
FF_LOGO_TYPE_DATA_RAW, //text data, printed as is
|
||||
FF_LOGO_TYPE_IMAGE_SIXEL, //image file, printed as sixel codes.
|
||||
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
|
||||
FF_LOGO_TYPE_IMAGE_KITTY_DIRECT, //image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)
|
||||
FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol
|
||||
FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa
|
||||
FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string
|
||||
FF_LOGO_TYPE_NONE, //--logo none
|
||||
} FFLogoType;
|
||||
|
||||
typedef struct FFLogoOptions
|
||||
{
|
||||
FFstrbuf source;
|
||||
FFLogoType type;
|
||||
FFstrbuf colors[FASTFETCH_LOGO_MAX_COLORS];
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t paddingTop;
|
||||
uint32_t paddingLeft;
|
||||
uint32_t paddingRight;
|
||||
bool printRemaining;
|
||||
bool preserveAspectRadio;
|
||||
bool recache;
|
||||
bool separate;
|
||||
|
||||
bool chafaFgOnly;
|
||||
FFstrbuf chafaSymbols;
|
||||
uint32_t chafaCanvasMode;
|
||||
uint32_t chafaColorSpace;
|
||||
uint32_t chafaDitherMode;
|
||||
} FFLogoOptions;
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "options/general.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffParseGeneralJsonConfig(FFGeneralOptions* options, yyjson_val* root)
|
||||
{
|
||||
yyjson_val* object = yyjson_obj_get(root, "general");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'general' 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, "allowSlowOperations"))
|
||||
options->allowSlowOperations = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
|
||||
options->multithreading = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
|
||||
options->processingTimeout = (int32_t) yyjson_get_int(val);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
|
||||
options->escapeBedrock = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "playerName"))
|
||||
ffStrbufSetS(&options->playerName, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osFile"))
|
||||
ffStrbufSetS(&options->osFile, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
|
||||
options->dsForceDrm = yyjson_get_bool(val);
|
||||
#elif defined(_WIN32)
|
||||
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
|
||||
options->wmiTimeout = (int32_t) yyjson_get_int(val);
|
||||
#endif
|
||||
|
||||
else
|
||||
return "Unknown general property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffParseGeneralCommandOptions(FFGeneralOptions* options, const char* key, const char* value)
|
||||
{
|
||||
if(ffStrEqualsIgnCase(key, "--allow-slow-operations"))
|
||||
options->allowSlowOperations = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--thread") || ffStrEqualsIgnCase(key, "--multithreading"))
|
||||
options->multithreading = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--processing-timeout"))
|
||||
options->processingTimeout = ffOptionParseInt32(key, value);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
else if(ffStrEqualsIgnCase(key, "--escape-bedrock"))
|
||||
options->escapeBedrock = ffOptionParseBoolean(value);
|
||||
else if(ffStrEqualsIgnCase(key, "--player-name"))
|
||||
ffOptionParseString(key, value, &options->playerName);
|
||||
else if (ffStrEqualsIgnCase(key, "--os-file"))
|
||||
ffOptionParseString(key, value, &options->osFile);
|
||||
else if(ffStrEqualsIgnCase(key, "--ds-force-drm"))
|
||||
options->dsForceDrm = ffOptionParseBoolean(value);
|
||||
#elif defined(_WIN32)
|
||||
else if (ffStrEqualsIgnCase(key, "--wmi-timeout"))
|
||||
options->wmiTimeout = ffOptionParseInt32(key, value);
|
||||
#endif
|
||||
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffInitGeneralOptions(FFGeneralOptions* options)
|
||||
{
|
||||
options->processingTimeout = 1000;
|
||||
options->allowSlowOperations = false;
|
||||
options->multithreading = true;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
options->escapeBedrock = true;
|
||||
ffStrbufInit(&options->playerName);
|
||||
ffStrbufInit(&options->osFile);
|
||||
options->dsForceDrm = false;
|
||||
#elif defined(_WIN32)
|
||||
options->wmiTimeout = 5000;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ffDestroyGeneralOptions(FF_MAYBE_UNUSED FFGeneralOptions* options)
|
||||
{
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufDestroy(&options->playerName);
|
||||
ffStrbufDestroy(&options->osFile);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
typedef struct FFGeneralOptions
|
||||
{
|
||||
bool allowSlowOperations;
|
||||
bool multithreading;
|
||||
int32_t processingTimeout;
|
||||
|
||||
// Module options that cannot be put in module option structure
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
FFstrbuf playerName;
|
||||
FFstrbuf osFile;
|
||||
bool escapeBedrock;
|
||||
bool dsForceDrm;
|
||||
#elif defined(_WIN32)
|
||||
int32_t wmiTimeout;
|
||||
#endif
|
||||
} FFGeneralOptions;
|
||||
|
||||
const char* ffParseGeneralJsonConfig(FFGeneralOptions* options, yyjson_val* root);
|
||||
bool ffParseGeneralCommandOptions(FFGeneralOptions* options, const char* key, const char* value);
|
||||
void ffInitGeneralOptions(FFGeneralOptions* options);
|
||||
void ffDestroyGeneralOptions(FFGeneralOptions* options);
|
||||
+1
-7
@@ -211,14 +211,8 @@ void ffDestroyLogoOptions(FFLogoOptions* options)
|
||||
ffStrbufDestroy(&options->colors[i]);
|
||||
}
|
||||
|
||||
const char* ffParseLogoJsonConfig(FFLogoOptions* options)
|
||||
const char* ffParseLogoJsonConfig(FFLogoOptions* options, yyjson_val* root)
|
||||
{
|
||||
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, "logo");
|
||||
if (!object) return NULL;
|
||||
if (yyjson_is_null(object))
|
||||
|
||||
+1
-1
@@ -48,5 +48,5 @@ typedef struct FFLogoOptions
|
||||
void ffInitLogoOptions(FFLogoOptions* options);
|
||||
bool ffParseLogoCommandOptions(FFLogoOptions* options, const char* key, const char* value);
|
||||
void ffDestroyLogoOptions(FFLogoOptions* options);
|
||||
const char* ffParseLogoJsonConfig(FFLogoOptions* options);
|
||||
const char* ffParseLogoJsonConfig(FFLogoOptions* options, yyjson_val* root);
|
||||
void ffGenerateLogoJsonConfig(FFLogoOptions* options, yyjson_mut_doc* doc);
|
||||
|
||||
@@ -162,7 +162,7 @@ struct FFWmiRecord
|
||||
if(!pEnumerator) return;
|
||||
|
||||
ULONG ret;
|
||||
bool ok = SUCCEEDED(pEnumerator->Next(instance.config.wmiTimeout, 1, &obj, &ret)) && ret;
|
||||
bool ok = SUCCEEDED(pEnumerator->Next(instance.config.general.wmiTimeout, 1, &obj, &ret)) && ret;
|
||||
if(!ok) obj = nullptr;
|
||||
}
|
||||
FFWmiRecord(const FFWmiRecord&) = delete;
|
||||
|
||||
Reference in New Issue
Block a user