Global: puts more fastfetch-only properties into FFdata

This commit is contained in:
李通洲
2026-01-15 15:03:38 +08:00
parent 79a11c4728
commit d3453de73c
17 changed files with 168 additions and 156 deletions
+1 -1
View File
@@ -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;
+3 -11
View File
@@ -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);
+24
View File
@@ -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;
+17 -14
View File
@@ -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
View File
@@ -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)
+6 -4
View File
@@ -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)
+5 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+2 -1
View File
@@ -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)
+2 -1
View File
@@ -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);
+2 -1
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);