mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-29 16:26:39 +01:00
JsonConfig: make it a special module
This commit is contained in:
@@ -313,6 +313,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/wifi.c
|
||||
src/modules/wm.c
|
||||
src/modules/wmtheme.c
|
||||
src/modules/jsonconfig/jsonconfig.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
src/util/FFvaluestore.c
|
||||
|
||||
@@ -3,116 +3,6 @@
|
||||
|
||||
#ifdef FF_HAVE_JSONC
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "modules/modules.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static inline bool parseModuleJsonObject(FFinstance* instance, const char* type, JSONCData* data, json_object* module)
|
||||
{
|
||||
return
|
||||
ffParseTitleJsonObject(instance, type, data, module) ||
|
||||
ffParseBatteryJsonObject(instance, type, data, module) ||
|
||||
ffParseCommandJsonObject(instance, type, data, module) ||
|
||||
ffParseOSJsonObject(instance, type, data, module) ||
|
||||
ffParseSeparatorJsonObject(instance, type, data, module) ||
|
||||
false;
|
||||
}
|
||||
|
||||
static inline void wrapJsoncFree(JSONCData* data)
|
||||
{
|
||||
assert(data);
|
||||
if (data->root)
|
||||
data->ffjson_object_put(data->root);
|
||||
}
|
||||
|
||||
static const char* parseModules(FFinstance* instance, JSONCData* data, json_object* modules)
|
||||
{
|
||||
array_list* list = data->ffjson_object_get_array(modules);
|
||||
if (!list) return "modules must be an array of strings or objects";
|
||||
|
||||
for (size_t idx = 0; idx < list->length; ++idx)
|
||||
{
|
||||
json_object* module = (json_object*) list->array[idx];
|
||||
const char* type = NULL;
|
||||
if (data->ffjson_object_is_type(module, json_type_string))
|
||||
{
|
||||
type = data->ffjson_object_get_string(module);
|
||||
module = NULL;
|
||||
}
|
||||
else if (data->ffjson_object_is_type(module, json_type_object))
|
||||
{
|
||||
type = data->ffjson_object_get_string(data->ffjson_object_object_get(module, "type"));
|
||||
if (!type) return "module object must contain a type key";
|
||||
}
|
||||
else
|
||||
return "modules must be an array of strings or objects";
|
||||
|
||||
if(!parseModuleJsonObject(instance, type, data, module))
|
||||
return "Unknown module type";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffJsonConfigParse(FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libjsonc, &instance->config.libJSONC, "dlopen libjson-c" FF_LIBRARY_EXTENSION" failed",
|
||||
#ifdef _WIN32
|
||||
"libjson-c-5" FF_LIBRARY_EXTENSION, -1
|
||||
#else
|
||||
"libjson-c" FF_LIBRARY_EXTENSION, 5
|
||||
#endif
|
||||
)
|
||||
JSONCData __attribute__((__cleanup__(wrapJsoncFree))) data = {};
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_tokener_parse)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_is_type)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_array)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_boolean)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_double)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_string_len)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_string)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_object)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_object_get)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_put)
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY content;
|
||||
ffStrbufInit(&content);
|
||||
FF_LIST_FOR_EACH(FFstrbuf, filename, instance->state.platform.configDirs)
|
||||
{
|
||||
uint32_t oldLength = filename->length;
|
||||
ffStrbufAppendS(filename, "fastfetch/config.json");
|
||||
bool success = ffAppendFileBuffer(filename->chars, &content);
|
||||
ffStrbufSubstrBefore(filename, oldLength);
|
||||
if (success) break;
|
||||
}
|
||||
|
||||
data.root = data.ffjson_tokener_parse(content.chars);
|
||||
if (!data.root)
|
||||
return "Failed to parse JSON config file";
|
||||
|
||||
lh_table* rootObject = data.ffjson_object_get_object(data.root);
|
||||
if (!rootObject)
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
struct lh_entry* entry;
|
||||
lh_foreach(rootObject, entry)
|
||||
{
|
||||
const char* key = (const char *)lh_entry_k(entry);
|
||||
json_object* val = (struct json_object *)lh_entry_v(entry);
|
||||
|
||||
if (strcmp(key, "modules") == 0)
|
||||
{
|
||||
const char* error = parseModules(instance, &data, val);
|
||||
if (error) return error;
|
||||
}
|
||||
else
|
||||
return "Unknown JSON config key in root object";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffJsonConfigParseModuleArgs(JSONCData* data, const char* key, json_object* val, FFModuleArgs* moduleArgs)
|
||||
{
|
||||
if(strcasecmp(key, "key") == 0)
|
||||
@@ -133,11 +23,4 @@ bool ffJsonConfigParseModuleArgs(JSONCData* data, const char* key, json_object*
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffParseJsonConfig(FF_MAYBE_UNUSED FFinstance* instance)
|
||||
{
|
||||
return "Fastfetch was compiled without json-c support";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,5 +25,3 @@ typedef struct JSONCData
|
||||
bool ffJsonConfigParseModuleArgs(JSONCData* data, const char* key, json_object* val, FFModuleArgs* moduleArgs);
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffJsonConfigParse(FFinstance* instance);
|
||||
|
||||
+27
-32
@@ -1494,6 +1494,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
|
||||
ffPrintSound(instance);
|
||||
else if(strcasecmp(line, "gamepad") == 0)
|
||||
ffPrintGamepad(instance);
|
||||
else if(strcasecmp(line, "jsonconfig") == 0)
|
||||
ffPrintJsonConfig(instance);
|
||||
else
|
||||
ffPrintErrorString(instance, line, 0, NULL, NULL, "<no implementation provided>");
|
||||
}
|
||||
@@ -1535,41 +1537,34 @@ int main(int argc, const char** argv)
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (ffStrbufIgnCaseEqualS(&data.structure, "Config"))
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data.structure.length)
|
||||
{
|
||||
ffJsonConfigParse(&instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data.structure.length)
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data.structure, startIndex, ':');
|
||||
data.structure.chars[colonIndex] = '\0';
|
||||
|
||||
uint64_t ms = 0;
|
||||
if(__builtin_expect(instance.config.stat, false))
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(&instance, &data, data.structure.chars + startIndex);
|
||||
|
||||
if(__builtin_expect(instance.config.stat, false))
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data.structure, startIndex, ':');
|
||||
data.structure.chars[colonIndex] = '\0';
|
||||
|
||||
uint64_t ms = 0;
|
||||
if(__builtin_expect(instance.config.stat, false))
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(&instance, &data, data.structure.chars + startIndex);
|
||||
|
||||
if(__builtin_expect(instance.config.stat, false))
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
|
||||
if(instance.config.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
|
||||
if(instance.config.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
ffFinish(&instance);
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "modules/jsonconfig/jsonconfig.h"
|
||||
#include "common/config.h"
|
||||
#include "common/printing.h"
|
||||
|
||||
#ifdef FF_HAVE_JSONC
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "modules/modules.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static inline bool parseModuleJsonObject(FFinstance* instance, const char* type, JSONCData* data, json_object* module)
|
||||
{
|
||||
return
|
||||
ffParseTitleJsonObject(instance, type, data, module) ||
|
||||
ffParseBatteryJsonObject(instance, type, data, module) ||
|
||||
ffParseCommandJsonObject(instance, type, data, module) ||
|
||||
ffParseOSJsonObject(instance, type, data, module) ||
|
||||
ffParseSeparatorJsonObject(instance, type, data, module) ||
|
||||
false;
|
||||
}
|
||||
|
||||
static inline void wrapJsoncFree(JSONCData* data)
|
||||
{
|
||||
assert(data);
|
||||
if (data->root)
|
||||
data->ffjson_object_put(data->root);
|
||||
}
|
||||
|
||||
static const char* parseModules(FFinstance* instance, JSONCData* data, json_object* modules)
|
||||
{
|
||||
array_list* list = data->ffjson_object_get_array(modules);
|
||||
if (!list) return "modules must be an array of strings or objects";
|
||||
|
||||
for (size_t idx = 0; idx < list->length; ++idx)
|
||||
{
|
||||
json_object* module = (json_object*) list->array[idx];
|
||||
const char* type = NULL;
|
||||
if (data->ffjson_object_is_type(module, json_type_string))
|
||||
{
|
||||
type = data->ffjson_object_get_string(module);
|
||||
module = NULL;
|
||||
}
|
||||
else if (data->ffjson_object_is_type(module, json_type_object))
|
||||
{
|
||||
type = data->ffjson_object_get_string(data->ffjson_object_object_get(module, "type"));
|
||||
if (!type) return "module object must contain a type key";
|
||||
}
|
||||
else
|
||||
return "modules must be an array of strings or objects";
|
||||
|
||||
if(!parseModuleJsonObject(instance, type, data, module))
|
||||
return "Unknown module type";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libjsonc, &instance->config.libJSONC, "dlopen libjson-c" FF_LIBRARY_EXTENSION" failed",
|
||||
#ifdef _WIN32
|
||||
"libjson-c-5" FF_LIBRARY_EXTENSION, -1
|
||||
#else
|
||||
"libjson-c" FF_LIBRARY_EXTENSION, 5
|
||||
#endif
|
||||
)
|
||||
JSONCData __attribute__((__cleanup__(wrapJsoncFree))) data = {};
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_tokener_parse)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_is_type)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_array)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_boolean)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_double)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_string_len)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_string)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_object)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_object_get)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_put)
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY content;
|
||||
ffStrbufInit(&content);
|
||||
FF_LIST_FOR_EACH(FFstrbuf, filename, instance->state.platform.configDirs)
|
||||
{
|
||||
uint32_t oldLength = filename->length;
|
||||
ffStrbufAppendS(filename, "fastfetch/config.json");
|
||||
bool success = ffAppendFileBuffer(filename->chars, &content);
|
||||
ffStrbufSubstrBefore(filename, oldLength);
|
||||
if (success) break;
|
||||
}
|
||||
|
||||
data.root = data.ffjson_tokener_parse(content.chars);
|
||||
if (!data.root)
|
||||
return "Failed to parse JSON config file";
|
||||
|
||||
lh_table* rootObject = data.ffjson_object_get_object(data.root);
|
||||
if (!rootObject)
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
struct lh_entry* entry;
|
||||
lh_foreach(rootObject, entry)
|
||||
{
|
||||
const char* key = (const char *)lh_entry_k(entry);
|
||||
json_object* val = (struct json_object *)lh_entry_v(entry);
|
||||
|
||||
if (strcmp(key, "modules") == 0)
|
||||
{
|
||||
const char* error = parseModules(instance, &data, val);
|
||||
if (error) return error;
|
||||
}
|
||||
else
|
||||
return "Unknown JSON config key in root object";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const char* printJsonConfig(FF_MAYBE_UNUSED FFinstance* instance)
|
||||
{
|
||||
return "Fastfetch was compiled without json-c support";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffPrintJsonConfig(FFinstance* instance)
|
||||
{
|
||||
const char* error = printJsonConfig(instance);
|
||||
if (error)
|
||||
ffPrintErrorString(instance, "JsonConfig", 0, NULL, NULL, "%s", error);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffPrintJsonConfig(FFinstance* instance);
|
||||
@@ -7,3 +7,4 @@
|
||||
#include "modules/command/command.h"
|
||||
#include "modules/separator/separator.h"
|
||||
#include "modules/title/title.h"
|
||||
#include "modules/jsonconfig/jsonconfig.h"
|
||||
|
||||
Reference in New Issue
Block a user