From b49f0b3d9c682fb3f3e818b6b6c3769149660a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jun 2026 20:19:13 +0800 Subject: [PATCH] Fastfetch: improves error message for config errors --- src/fastfetch.c | 20 +++++++++++++------- src/options/display.c | 3 ++- src/options/display.h | 2 +- src/options/general.c | 3 ++- src/options/general.h | 2 +- src/options/logo.c | 3 ++- src/options/logo.h | 2 +- 7 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index a5e76d1a0..e64440925 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -404,20 +404,26 @@ static bool parseJsoncFile(FFdata* data, const char* path, yyjson_read_flag flg) } { - const char* error = NULL; - 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"; + fputs("JsonConfig Error: Invalid JSON config format. Root value must be an object", stderr); + exit(477); } + yyjson_val* problematicKey = NULL; + const char* error = NULL; + const char* problematicModule = NULL; if ( error || - (error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) || - (error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) || - (error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) || + ((error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root, &problematicKey)) && (problematicModule = "logo")) || + ((error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root, &problematicKey)) && (problematicModule = "general")) || + ((error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root, &problematicKey)) && (problematicModule = "display")) || false) { - fprintf(stderr, "JsonConfig Error: %s\n", error); + if (problematicKey) { + fprintf(stderr, "JsonConfig Error (%s.%s): %s\n", problematicModule, unsafe_yyjson_get_str(problematicKey), error); + } else { + fprintf(stderr, "JsonConfig Error (%s): %s\n", problematicModule, error); + } exit(477); } } diff --git a/src/options/display.c b/src/options/display.c index ec80a3723..62eaea8ec 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -7,7 +7,7 @@ #include -const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root) { +const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root, yyjson_val** pkey) { yyjson_val* object = yyjson_obj_get(root, "display"); if (!object) { return NULL; @@ -19,6 +19,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val *key, *val; size_t idx, max; yyjson_obj_foreach (object, idx, max, key, val) { + *pkey = key; if (unsafe_yyjson_equals_str(key, "stat")) { if (yyjson_is_bool(val)) { if (yyjson_get_bool(val)) { diff --git a/src/options/display.h b/src/options/display.h index 8c674eabc..6017291f5 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -90,7 +90,7 @@ typedef struct FFOptionsDisplay { FFlist constants; // list of FFstrbuf } FFOptionsDisplay; -const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root); +const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root, yyjson_val** pkey); bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key, const char* value); void ffOptionsInitDisplay(FFOptionsDisplay* options); void ffOptionsDestroyDisplay(FFOptionsDisplay* options); diff --git a/src/options/general.c b/src/options/general.c index 6257a0f17..1e1355df8 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -6,7 +6,7 @@ #include -const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_val* root) { +const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_val* root, yyjson_val** pkey) { yyjson_val* object = yyjson_obj_get(root, "general"); if (!object) { return NULL; @@ -18,6 +18,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va yyjson_val *key, *val; size_t idx, max; yyjson_obj_foreach (object, idx, max, key, val) { + *pkey = key; if (unsafe_yyjson_equals_str(key, "thread")) { options->multithreading = yyjson_get_bool(val); } else if (unsafe_yyjson_equals_str(key, "processingTimeout")) { diff --git a/src/options/general.h b/src/options/general.h index 454ca6031..b58d6c9e3 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -20,7 +20,7 @@ typedef struct FFOptionsGeneral { #endif } FFOptionsGeneral; -const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_val* root); +const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_val* root, yyjson_val** pkey); bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key, const char* value); void ffOptionsInitGeneral(FFOptionsGeneral* options); void ffOptionsDestroyGeneral(FFOptionsGeneral* options); diff --git a/src/options/logo.c b/src/options/logo.c index e1d647404..99e22c99c 100644 --- a/src/options/logo.c +++ b/src/options/logo.c @@ -216,7 +216,7 @@ void ffOptionsDestroyLogo(FFOptionsLogo* options) { } } -const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* root) { +const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* root, yyjson_val** pkey) { yyjson_val* object = yyjson_obj_get(root, "logo"); if (!object) { return NULL; @@ -242,6 +242,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo yyjson_val *key, *val; size_t idx, max; yyjson_obj_foreach (object, idx, max, key, val) { + *pkey = key; if (unsafe_yyjson_equals_str(key, "type")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { diff --git a/src/options/logo.h b/src/options/logo.h index c77c67860..7a71531d9 100644 --- a/src/options/logo.h +++ b/src/options/logo.h @@ -57,5 +57,5 @@ typedef struct FFOptionsLogo { 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); +const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* root, yyjson_val** pkey); void ffOptionsGenerateLogoJsonConfig(FFdata* data, FFOptionsLogo* options);