mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Global: puts more fastfetch-only properties into FFdata
This commit is contained in:
@@ -18,7 +18,7 @@ typedef struct FFPlatform
|
||||
FFstrbuf cacheDir; // Trailing slash included
|
||||
FFlist configDirs; // List of FFstrbuf, trailing slash included
|
||||
FFlist dataDirs; // List of FFstrbuf, trailing slash included
|
||||
FFstrbuf exePath; // The real path of current exe
|
||||
FFstrbuf exePath; // The real path of current exe (empty if unavailable)
|
||||
|
||||
FFstrbuf userName;
|
||||
FFstrbuf fullUserName;
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
// Things only needed by fastfetch
|
||||
typedef struct FFdata
|
||||
{
|
||||
FFstrbuf structure;
|
||||
FFstrbuf structureDisabled;
|
||||
bool configLoaded;
|
||||
} FFdata;
|
||||
#include "common/ffdata.h"
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffPrintCommandOption(FFdata* data);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data);
|
||||
bool ffParseModuleOptions(const char* key, const char* value);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFDataResultDocType
|
||||
{
|
||||
FF_RESULT_DOC_TYPE_DEFAULT = 0,
|
||||
FF_RESULT_DOC_TYPE_JSON,
|
||||
FF_RESULT_DOC_TYPE_CONFIG,
|
||||
FF_RESULT_DOC_TYPE_CONFIG_FULL,
|
||||
} FFDataResultDocType;
|
||||
|
||||
// FFdata aggregates configuration, generation parameters, and output state used by fastfetch.
|
||||
// It holds the parsed configuration document, a mutable JSON document for results, and related metadata.
|
||||
typedef struct FFdata
|
||||
{
|
||||
yyjson_doc* configDoc; // Parsed JSON configuration document
|
||||
yyjson_mut_doc* resultDoc; // Mutable JSON document for storing results
|
||||
FFstrbuf structure; // Custom output structure from command line
|
||||
FFstrbuf structureDisabled; // Disabled modules in the output structure from command line
|
||||
FFstrbuf genConfigPath; // Path to generate configuration file
|
||||
FFDataResultDocType docType; // Type of result document
|
||||
bool configLoaded;
|
||||
} FFdata;
|
||||
@@ -127,8 +127,10 @@ void ffPrepareCommandOption(FFdata* data)
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
|
||||
static void genJsonConfig(FFdata* data, FFModuleBaseInfo* baseInfo, void* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
|
||||
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
|
||||
if (!modules)
|
||||
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
|
||||
@@ -136,7 +138,7 @@ static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
|
||||
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&type);
|
||||
|
||||
if (instance.state.fullConfig)
|
||||
if (data->docType == FF_RESULT_DOC_TYPE_CONFIG_FULL)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
|
||||
@@ -155,8 +157,9 @@ static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
|
||||
static void genJsonResult(FFdata* data, FFModuleBaseInfo* baseInfo, void* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJsonResult)
|
||||
@@ -166,9 +169,9 @@ static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
|
||||
}
|
||||
|
||||
static void parseStructureCommand(
|
||||
FFdata* data,
|
||||
const char* line,
|
||||
void (*fn)(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* jsonDoc),
|
||||
yyjson_mut_doc* jsonDoc
|
||||
void (*fn)(FFdata*, FFModuleBaseInfo* baseInfo, void* options)
|
||||
)
|
||||
{
|
||||
if(ffCharIsEnglishAlphabet(line[0]))
|
||||
@@ -180,8 +183,8 @@ static void parseStructureCommand(
|
||||
{
|
||||
uint8_t optionBuf[FF_OPTION_MAX_SIZE];
|
||||
baseInfo->initOptions(optionBuf);
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn(baseInfo, optionBuf, jsonDoc);
|
||||
if (__builtin_expect(data->resultDoc != NULL, false))
|
||||
fn(data, baseInfo, optionBuf);
|
||||
else
|
||||
baseInfo->printModule(optionBuf);
|
||||
baseInfo->destroyOptions(optionBuf);
|
||||
@@ -193,7 +196,7 @@ static void parseStructureCommand(
|
||||
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
void ffPrintCommandOption(FFdata* data)
|
||||
{
|
||||
//Parse the structure and call the modules
|
||||
int32_t thres = instance.config.display.stat;
|
||||
@@ -209,16 +212,16 @@ void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
if(thres >= 0)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(moduleType, genJsonResult, jsonDoc);
|
||||
parseStructureCommand(data, moduleType, genJsonResult);
|
||||
|
||||
if(thres >= 0)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
|
||||
if (jsonDoc)
|
||||
if (data->resultDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(data->resultDoc->root);
|
||||
yyjson_mut_obj_add_real(data->resultDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -236,7 +239,7 @@ void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
}
|
||||
}
|
||||
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
@@ -249,6 +252,6 @@ void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':'))
|
||||
continue;
|
||||
|
||||
parseStructureCommand(moduleType, genJsonConfig, jsonDoc);
|
||||
parseStructureCommand(data, moduleType, genJsonConfig);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-10
@@ -28,8 +28,6 @@ static void initState(FFstate* state)
|
||||
state->titleFqdn = false;
|
||||
|
||||
ffPlatformInit(&state->platform);
|
||||
state->configDoc = NULL;
|
||||
state->resultDoc = NULL;
|
||||
state->dynamicInterval = 0;
|
||||
|
||||
{
|
||||
@@ -96,8 +94,8 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
|
||||
void ffStart(void)
|
||||
{
|
||||
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe;
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe;
|
||||
|
||||
#ifdef _WIN32
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
@@ -124,7 +122,7 @@ void ffStart(void)
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
if(!instance.config.display.pipe && !instance.state.resultDoc)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(ffHideCursor)
|
||||
@@ -138,8 +136,6 @@ void ffStart(void)
|
||||
fputs("\033[?1049h\033[H", stdout); // Enable alternate buffer
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
ffLogoPrint();
|
||||
}
|
||||
|
||||
void ffFinish(void)
|
||||
@@ -157,9 +153,6 @@ static void destroyConfig(void)
|
||||
static void destroyState(void)
|
||||
{
|
||||
ffPlatformDestroy(&instance.state.platform);
|
||||
yyjson_doc_free(instance.state.configDoc);
|
||||
yyjson_mut_doc_free(instance.state.resultDoc);
|
||||
ffStrbufDestroy(&instance.state.genConfigPath);
|
||||
}
|
||||
|
||||
void ffDestroyInstance(void)
|
||||
|
||||
@@ -230,9 +230,10 @@ static bool matchesJsonArray(const char* str, yyjson_val* val)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
static const char* printJsonConfig(FFdata* data, bool prepare)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
yyjson_mut_doc* jsonDoc = data->resultDoc;
|
||||
yyjson_val* const root = yyjson_doc_get_root(data->configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
@@ -329,9 +330,10 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
void ffPrintJsonConfig(FFdata* data, bool prepare)
|
||||
{
|
||||
const char* error = printJsonConfig(prepare, jsonDoc);
|
||||
yyjson_mut_doc* jsonDoc = data->resultDoc;
|
||||
const char* error = printJsonConfig(data, prepare);
|
||||
if (error)
|
||||
{
|
||||
if (jsonDoc)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "common/ffdata.h"
|
||||
#include "common/option.h"
|
||||
|
||||
bool ffJsonConfigParseModuleArgs(yyjson_val* key, yyjson_val* val, FFModuleArgs* moduleArgs);
|
||||
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc);
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* moduleArgs);
|
||||
|
||||
yyjson_api_inline yyjson_mut_val* yyjson_mut_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) {
|
||||
return yyjson_mut_strncpy(doc, buf->chars, buf->length);
|
||||
@@ -23,3 +22,6 @@ yyjson_api_inline bool yyjson_mut_arr_add_strbuf(yyjson_mut_doc *doc,
|
||||
const FFstrbuf* buf) {
|
||||
return yyjson_mut_arr_add_strncpy(doc, obj, buf->chars, buf->length);
|
||||
}
|
||||
|
||||
void ffPrintJsonConfig(FFdata* data, bool prepare);
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* moduleArgs);
|
||||
|
||||
+73
-64
@@ -1,4 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/ffdata.h"
|
||||
#include "detection/version/version.h"
|
||||
#include "logo/logo.h"
|
||||
#include "common/commandoption.h"
|
||||
@@ -379,16 +380,16 @@ static void listModules(bool pretty)
|
||||
}
|
||||
}
|
||||
|
||||
static bool parseJsoncFile(const char* path, yyjson_read_flag flg)
|
||||
static bool parseJsoncFile(FFdata* data, const char* path, yyjson_read_flag flg)
|
||||
{
|
||||
assert(!instance.state.configDoc);
|
||||
assert(!data->configDoc);
|
||||
|
||||
{
|
||||
yyjson_read_err error;
|
||||
instance.state.configDoc = path
|
||||
data->configDoc = path
|
||||
? yyjson_read_file(path, flg, NULL, &error)
|
||||
: yyjson_read_fp(stdin, flg, NULL, &error);
|
||||
if (!instance.state.configDoc)
|
||||
if (!data->configDoc)
|
||||
{
|
||||
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
|
||||
{
|
||||
@@ -412,7 +413,7 @@ static bool parseJsoncFile(const char* path, yyjson_read_flag flg)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
yyjson_val* const root = yyjson_doc_get_root(data->configDoc);
|
||||
if (!yyjson_is_obj(root))
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
@@ -432,8 +433,14 @@ static bool parseJsoncFile(const char* path, yyjson_read_flag flg)
|
||||
}
|
||||
|
||||
|
||||
static void generateConfigFile(bool force, const char* filePath, bool fullConfig)
|
||||
static void generateConfigFile(FFdata* data, bool force, const char* filePath, bool fullConfig)
|
||||
{
|
||||
if (data->resultDoc)
|
||||
{
|
||||
fprintf(stderr, "Error: duplicated `--gen-config` or `--format json` flags found\n");
|
||||
exit(477);
|
||||
}
|
||||
|
||||
if (!filePath)
|
||||
{
|
||||
if (instance.state.platform.configDirs.length == 0)
|
||||
@@ -443,22 +450,23 @@ static void generateConfigFile(bool force, const char* filePath, bool fullConfig
|
||||
}
|
||||
|
||||
FFstrbuf* configDir = FF_LIST_FIRST(FFstrbuf, instance.state.platform.configDirs);
|
||||
ffStrbufEnsureFixedLengthFree(&instance.state.genConfigPath, configDir->length + strlen("fastfetch/config.jsonc"));
|
||||
ffStrbufSet(&instance.state.genConfigPath, configDir);
|
||||
ffStrbufAppendS(&instance.state.genConfigPath, "fastfetch/config.jsonc");
|
||||
ffStrbufEnsureFixedLengthFree(&data->genConfigPath, configDir->length + strlen("fastfetch/config.jsonc"));
|
||||
ffStrbufSet(&data->genConfigPath, configDir);
|
||||
ffStrbufAppendS(&data->genConfigPath, "fastfetch/config.jsonc");
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSetS(&instance.state.genConfigPath, filePath);
|
||||
ffStrbufSetS(&data->genConfigPath, filePath);
|
||||
}
|
||||
|
||||
if (!force && ffPathExists(instance.state.genConfigPath.chars, FF_PATHTYPE_ANY))
|
||||
if (!force && ffPathExists(data->genConfigPath.chars, FF_PATHTYPE_ANY))
|
||||
{
|
||||
fprintf(stderr, "Error: file `%s` exists. Use `--gen-config%s-force` to overwrite\n", instance.state.genConfigPath.chars, fullConfig ? "-full" : "");
|
||||
fprintf(stderr, "Error: file `%s` exists. Use `--gen-config%s-force` to overwrite\n", data->genConfigPath.chars, fullConfig ? "-full" : "");
|
||||
exit(477);
|
||||
}
|
||||
|
||||
instance.state.fullConfig = fullConfig;
|
||||
data->docType = fullConfig ? FF_RESULT_DOC_TYPE_CONFIG_FULL : FF_RESULT_DOC_TYPE_CONFIG;
|
||||
data->resultDoc = yyjson_mut_doc_new(NULL);
|
||||
}
|
||||
|
||||
static void optionParseConfigFile(FFdata* data, const char* key, const char* value)
|
||||
@@ -482,7 +490,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
|
||||
if (value[0] == '-' && value[1] == '\0')
|
||||
{
|
||||
parseJsoncFile(NULL, false);
|
||||
parseJsoncFile(data, NULL, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -503,7 +511,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
? YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS
|
||||
: YYJSON_READ_JSON5;
|
||||
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
|
||||
|
||||
//Try to load as a relative path with the config directory
|
||||
|
||||
@@ -515,7 +523,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
|
||||
}
|
||||
|
||||
//Try to load as a preset
|
||||
@@ -528,7 +536,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
|
||||
}
|
||||
|
||||
//Try to load as a relative path with the directory of fastfetch binary, for Windows support
|
||||
@@ -543,7 +551,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
ffStrbufAppendS(&absolutePath, value);
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
|
||||
|
||||
// Try {exePath}/presets/
|
||||
ffStrbufSubstrBefore(&absolutePath, lastSlash);
|
||||
@@ -551,7 +559,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
ffStrbufAppendS(&absolutePath, value);
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
|
||||
}
|
||||
|
||||
//File not found
|
||||
@@ -566,24 +574,17 @@ static void printVersion()
|
||||
printf("%s %s%s%s (%s)\n", result->projectName, result->version, result->versionTweak, result->debugMode ? "-debug" : "", result->architecture);
|
||||
}
|
||||
|
||||
static void enableJsonOutput(bool enable)
|
||||
static void enableJsonOutput(FFdata* data)
|
||||
{
|
||||
if (!enable)
|
||||
if (data->resultDoc)
|
||||
{
|
||||
if (instance.state.resultDoc)
|
||||
{
|
||||
yyjson_mut_doc_free(instance.state.resultDoc);
|
||||
instance.state.resultDoc = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!instance.state.resultDoc)
|
||||
{
|
||||
instance.state.resultDoc = yyjson_mut_doc_new(NULL);
|
||||
yyjson_mut_doc_set_root(instance.state.resultDoc, yyjson_mut_arr(instance.state.resultDoc));
|
||||
}
|
||||
fprintf(stderr, "Error: duplicated `--gen-config` or `--format json` flags found\n");
|
||||
exit(477);
|
||||
}
|
||||
|
||||
data->resultDoc = yyjson_mut_doc_new(NULL);
|
||||
data->docType = FF_RESULT_DOC_TYPE_JSON;
|
||||
yyjson_mut_doc_set_root(data->resultDoc, yyjson_mut_arr(data->resultDoc));
|
||||
}
|
||||
|
||||
static void parseCommand(FFdata* data, char* key, char* value)
|
||||
@@ -668,24 +669,26 @@ static void parseCommand(FFdata* data, char* key, char* value)
|
||||
exit(0);
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "--gen-config"))
|
||||
generateConfigFile(false, value, false);
|
||||
generateConfigFile(data, false, value, false);
|
||||
else if(ffStrEqualsIgnCase(key, "--gen-config-force"))
|
||||
generateConfigFile(true, value, false);
|
||||
generateConfigFile(data, true, value, false);
|
||||
else if(ffStrEqualsIgnCase(key, "--gen-config-full"))
|
||||
generateConfigFile(false, value, true);
|
||||
generateConfigFile(data, false, value, true);
|
||||
else if(ffStrEqualsIgnCase(key, "--gen-config-full-force"))
|
||||
generateConfigFile(true, value, true);
|
||||
generateConfigFile(data, true, value, true);
|
||||
else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--config"))
|
||||
optionParseConfigFile(data, key, value);
|
||||
else if(ffStrEqualsIgnCase(key, "-j") || ffStrEqualsIgnCase(key, "--json"))
|
||||
enableJsonOutput(ffOptionParseBoolean(value));
|
||||
{
|
||||
if (ffOptionParseBoolean(value)) enableJsonOutput(data);
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "--format"))
|
||||
{
|
||||
enableJsonOutput(!!ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
|
||||
if (!!ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
|
||||
{ "default", false},
|
||||
{ "json", true },
|
||||
{},
|
||||
}));
|
||||
})) enableJsonOutput(data);
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "--dynamic-interval"))
|
||||
instance.state.dynamicInterval = ffOptionParseUInt32(key, value); // seconds to milliseconds
|
||||
@@ -720,21 +723,21 @@ static void parseOption(FFdata* data, const char* key, const char* value)
|
||||
}
|
||||
}
|
||||
|
||||
static void parseConfigFiles(void)
|
||||
static void parseConfigFiles(FFdata* data)
|
||||
{
|
||||
if (__builtin_expect(instance.state.genConfigPath.length == 0, true))
|
||||
if (__builtin_expect(data->genConfigPath.length == 0, true))
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFstrbuf, dir, instance.state.platform.configDirs)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
|
||||
ffStrbufAppendS(dir, "fastfetch/config.jsonc");
|
||||
bool success = parseJsoncFile(dir->chars, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS);
|
||||
bool success = parseJsoncFile(data, dir->chars, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (success) return;
|
||||
|
||||
ffStrbufAppendS(dir, "fastfetch/config.json5");
|
||||
success = parseJsoncFile(dir->chars, YYJSON_READ_JSON5);
|
||||
success = parseJsoncFile(data, dir->chars, YYJSON_READ_JSON5);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (success) return;
|
||||
}
|
||||
@@ -772,10 +775,10 @@ static void parseArguments(FFdata* data, int argc, char** argv, void (*parser)(F
|
||||
|
||||
static void run(FFdata* data)
|
||||
{
|
||||
const bool useJsonConfig = data->structure.length == 0 && instance.state.configDoc;
|
||||
const bool useJsonConfig = data->structure.length == 0 && data->configDoc;
|
||||
|
||||
if (useJsonConfig)
|
||||
ffPrintJsonConfig(true /* prepare */, instance.state.resultDoc);
|
||||
ffPrintJsonConfig(data, true /* prepare */);
|
||||
else
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
@@ -786,6 +789,9 @@ static void run(FFdata* data)
|
||||
|
||||
ffStart();
|
||||
|
||||
if (!data->resultDoc)
|
||||
ffLogoPrint();
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!instance.config.display.noBuffer) fflush(stdout);
|
||||
#endif
|
||||
@@ -793,9 +799,9 @@ static void run(FFdata* data)
|
||||
while (true)
|
||||
{
|
||||
if (useJsonConfig)
|
||||
ffPrintJsonConfig(false, instance.state.resultDoc);
|
||||
ffPrintJsonConfig(data, false);
|
||||
else
|
||||
ffPrintCommandOption(data, instance.state.resultDoc);
|
||||
ffPrintCommandOption(data);
|
||||
|
||||
if (instance.state.dynamicInterval > 0)
|
||||
{
|
||||
@@ -807,8 +813,8 @@ static void run(FFdata* data)
|
||||
break;
|
||||
}
|
||||
|
||||
if (instance.state.resultDoc)
|
||||
yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
|
||||
if (data->resultDoc)
|
||||
yyjson_mut_write_fp(stdout, data->resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
|
||||
else
|
||||
{
|
||||
if (instance.config.logo.printRemaining)
|
||||
@@ -819,20 +825,20 @@ static void run(FFdata* data)
|
||||
|
||||
static void writeConfigFile(FFdata* data)
|
||||
{
|
||||
const FFstrbuf* filename = &instance.state.genConfigPath;
|
||||
const FFstrbuf* filename = &data->genConfigPath;
|
||||
|
||||
yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL);
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
yyjson_mut_val* root = yyjson_mut_obj(doc);
|
||||
yyjson_mut_doc_set_root(doc, root);
|
||||
yyjson_mut_obj_add_str(doc, root, "$schema", "https://github.com/fastfetch-cli/fastfetch/raw/master/doc/json_schema.json");
|
||||
|
||||
if (instance.state.fullConfig)
|
||||
if (data->docType == FF_RESULT_DOC_TYPE_CONFIG_FULL)
|
||||
{
|
||||
ffOptionsGenerateLogoJsonConfig(&instance.config.logo, doc);
|
||||
ffOptionsGenerateDisplayJsonConfig(&instance.config.display, doc);
|
||||
ffOptionsGenerateGeneralJsonConfig(&instance.config.general, doc);
|
||||
ffOptionsGenerateLogoJsonConfig(data, &instance.config.logo);
|
||||
ffOptionsGenerateDisplayJsonConfig(data, &instance.config.display);
|
||||
ffOptionsGenerateGeneralJsonConfig(data, &instance.config.general);
|
||||
}
|
||||
ffMigrateCommandOptionToJsonc(data, doc);
|
||||
ffMigrateCommandOptionToJsonc(data);
|
||||
|
||||
if (ffStrbufEqualS(filename, "-"))
|
||||
yyjson_mut_write_fp(stdout, doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
|
||||
@@ -857,8 +863,6 @@ static void writeConfigFile(FFdata* data)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
yyjson_mut_doc_free(doc);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -869,24 +873,29 @@ int main(int argc, char** argv)
|
||||
//Data stores things only needed for the configuration of fastfetch
|
||||
FFdata data = {
|
||||
.structure = ffStrbufCreate(),
|
||||
.configLoaded = false,
|
||||
.structureDisabled = ffStrbufCreate(),
|
||||
.genConfigPath = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
parseArguments(&data, argc, argv, parseCommand);
|
||||
if(instance.state.dynamicInterval && instance.state.resultDoc)
|
||||
if(instance.state.dynamicInterval && data.resultDoc)
|
||||
{
|
||||
fprintf(stderr, "Error: --dynamic-interval cannot be used with --json\n");
|
||||
exit(400);
|
||||
}
|
||||
|
||||
if(!data.configLoaded && !getenv("NO_CONFIG"))
|
||||
parseConfigFiles();
|
||||
parseConfigFiles(&data);
|
||||
parseArguments(&data, argc, argv, (void*) parseOption);
|
||||
|
||||
if (__builtin_expect(instance.state.genConfigPath.length == 0, true))
|
||||
if (__builtin_expect(data.genConfigPath.length == 0, true))
|
||||
run(&data);
|
||||
else
|
||||
writeConfigFile(&data);
|
||||
|
||||
ffStrbufDestroy(&data.structure);
|
||||
ffStrbufDestroy(&data.structureDisabled);
|
||||
yyjson_doc_free(data.configDoc);
|
||||
yyjson_mut_doc_free(data.resultDoc);
|
||||
ffStrbufDestroy(&data.genConfigPath);
|
||||
}
|
||||
|
||||
+1
-12
@@ -5,12 +5,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef FF_USE_SYSTEM_YYJSON
|
||||
#include <yyjson.h>
|
||||
#else
|
||||
#include "3rdparty/yyjson/yyjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
@@ -40,13 +34,8 @@ typedef struct FFstate
|
||||
uint32_t keysHeight;
|
||||
bool terminalLightTheme;
|
||||
bool titleFqdn;
|
||||
|
||||
FFPlatform platform;
|
||||
yyjson_doc* configDoc;
|
||||
yyjson_mut_doc* resultDoc;
|
||||
FFstrbuf genConfigPath;
|
||||
bool fullConfig;
|
||||
uint32_t dynamicInterval;
|
||||
FFPlatform platform;
|
||||
} FFstate;
|
||||
|
||||
typedef struct FFinstance
|
||||
|
||||
+4
-1
@@ -16,9 +16,12 @@ int main(void)
|
||||
instance.config.display.freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER;
|
||||
instance.config.display.sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER;
|
||||
|
||||
// Logo printing and other preparation stuff
|
||||
// Some preparation stuff
|
||||
ffStart();
|
||||
|
||||
// Print logo
|
||||
ffLogoPrint();
|
||||
|
||||
// Print all modules
|
||||
{
|
||||
__attribute__((cleanup(ffDestroyTitleOptions))) FFTitleOptions options;
|
||||
|
||||
+2
-11
@@ -424,7 +424,8 @@ static void logoPrintStruct(const FFlogo* logo)
|
||||
|
||||
static void logoPrintNone(void)
|
||||
{
|
||||
logoApplyColors(logoGetBuiltinDetected(FF_LOGO_SIZE_NORMAL), false);
|
||||
if (!instance.config.display.pipe)
|
||||
logoApplyColors(logoGetBuiltinDetected(FF_LOGO_SIZE_NORMAL), false);
|
||||
instance.state.logoHeight = 0;
|
||||
instance.state.logoWidth = 0;
|
||||
}
|
||||
@@ -614,16 +615,6 @@ static bool logoTryKnownType(void)
|
||||
|
||||
void ffLogoPrint(void)
|
||||
{
|
||||
//When generate JSON result, 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.state.resultDoc)
|
||||
{
|
||||
instance.state.logoHeight = 0;
|
||||
instance.state.logoWidth = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const FFOptionsLogo* options = &instance.config.logo;
|
||||
|
||||
if (options->type == FF_LOGO_TYPE_NONE)
|
||||
|
||||
@@ -909,8 +909,9 @@ void ffOptionsDestroyDisplay(FFOptionsDisplay* options)
|
||||
ffListDestroy(&options->constants);
|
||||
}
|
||||
|
||||
void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_doc* doc)
|
||||
void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, doc->root, "display");
|
||||
|
||||
if (options->stat <= 0)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/ffdata.h"
|
||||
#include "common/percent.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/FFlist.h"
|
||||
@@ -98,4 +99,4 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
|
||||
bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key, const char* value);
|
||||
void ffOptionsInitDisplay(FFOptionsDisplay* options);
|
||||
void ffOptionsDestroyDisplay(FFOptionsDisplay* options);
|
||||
void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_doc* doc);
|
||||
void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options);
|
||||
|
||||
@@ -117,8 +117,9 @@ void ffOptionsDestroyGeneral(FF_MAYBE_UNUSED FFOptionsGeneral* options)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_doc* doc)
|
||||
void ffOptionsGenerateGeneralJsonConfig(FFdata* data, FFOptionsGeneral* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, doc->root, "general");
|
||||
|
||||
yyjson_mut_obj_add_bool(doc, obj, "thread", options->multithreading);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/ffdata.h"
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFDsForceDrmType
|
||||
{
|
||||
@@ -28,4 +28,4 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
|
||||
bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key, const char* value);
|
||||
void ffOptionsInitGeneral(FFOptionsGeneral* options);
|
||||
void ffOptionsDestroyGeneral(FFOptionsGeneral* options);
|
||||
void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_doc* doc);
|
||||
void ffOptionsGenerateGeneralJsonConfig(FFdata* data, FFOptionsGeneral* options);
|
||||
|
||||
+2
-1
@@ -466,8 +466,9 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc)
|
||||
void ffOptionsGenerateLogoJsonConfig(FFdata* data, FFOptionsLogo* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
yyjson_mut_val* obj = yyjson_mut_obj(doc);
|
||||
|
||||
switch (options->type)
|
||||
|
||||
+19
-19
@@ -1,28 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/ffdata.h"
|
||||
|
||||
#define FASTFETCH_LOGO_MAX_NAMES 9
|
||||
#define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9)
|
||||
#define FASTFETCH_LOGO_MAX_COLORS 9 // two digits would make parsing much more complicated (index 1 - 9)
|
||||
|
||||
typedef enum __attribute__((__packed__)) 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_COMMAND_RAW, //command to generate 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_KITTY_ICAT, //image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed"
|
||||
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
|
||||
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_COMMAND_RAW, // command to generate 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_KITTY_ICAT, // image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed"
|
||||
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`, but still applies colors to the system information output (unless `--pipe` is set)
|
||||
} FFLogoType;
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFLogoPosition
|
||||
@@ -58,4 +58,4 @@ void ffOptionsInitLogo(FFOptionsLogo* options);
|
||||
bool ffOptionsParseLogoCommandLine(FFOptionsLogo* options, const char* key, const char* value);
|
||||
void ffOptionsDestroyLogo(FFOptionsLogo* options);
|
||||
const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* root);
|
||||
void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc);
|
||||
void ffOptionsGenerateLogoJsonConfig(FFdata* data, FFOptionsLogo* options);
|
||||
|
||||
Reference in New Issue
Block a user