mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Fastfetch: adds interactive --gen-config mode
removes `--gen-config-*` flags (merged into `--gen-config`)
This commit is contained in:
@@ -434,6 +434,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/impl/font.c
|
||||
src/common/impl/format.c
|
||||
src/common/impl/frequency.c
|
||||
src/common/impl/genconfig.c
|
||||
src/common/impl/init.c
|
||||
src/common/impl/jsonconfig.c
|
||||
src/common/impl/library.c
|
||||
|
||||
+2
-20
@@ -107,26 +107,8 @@
|
||||
},
|
||||
{
|
||||
"long": "gen-config",
|
||||
"desc": "Generate a minimal config file at the specified path",
|
||||
"remark": "Defaults to \"~/.config/fastfetch/config.jsonc\". Prints the generated config if <path> is \"-\"",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "gen-config-full",
|
||||
"desc": "Generate a full config file with all optional settings at the specified path",
|
||||
"remark": "Defaults to \"~/.config/fastfetch/config.jsonc\". Prints the generated config if <path> is \"-\"",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "gen-config-force",
|
||||
"desc": "Generate a config file at the specified path, overwriting any existing file",
|
||||
"remark": "Defaults to \"~/.config/fastfetch/config.jsonc\"",
|
||||
"desc": "Interactively generate a config file at the specified path",
|
||||
"remark": "Opens an interactive configuration UI when run in a terminal. Falls back to non-interactive generation when env-var `$NO_COLOR` is set or stdin/stdout is not a TTY. Defaults to \"~/.config/fastfetch/config.jsonc\". Prints the generated config if <path> is \"-\"",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"optional": true
|
||||
|
||||
@@ -19,4 +19,5 @@ typedef struct FFdata {
|
||||
FFstrbuf genConfigPath; // Path to generate configuration file
|
||||
FFDataResultDocType docType; // Type of result document
|
||||
bool configLoaded;
|
||||
bool genConfigInteractive; // `--gen-config` entered the interactive CUI
|
||||
} FFdata;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/ffdata.h"
|
||||
|
||||
// Runs the interactive config generation CUI.
|
||||
//
|
||||
// On success (the user saved the config), it sets `data->structure` to the user chosen
|
||||
// module structure and `instance.config.logo.type` to the user chosen logo type, creates
|
||||
// the result document and returns true. The caller is expected to call `writeConfigFile`.
|
||||
// Returns false if the user quits without saving.
|
||||
bool ffGenConfigInteractive(FFdata* data);
|
||||
File diff suppressed because it is too large
Load Diff
+47
-16
@@ -3,6 +3,7 @@
|
||||
#include "detection/version/version.h"
|
||||
#include "logo/logo.h"
|
||||
#include "common/commandoption.h"
|
||||
#include "common/genconfig.h"
|
||||
#include "common/init.h"
|
||||
#include "common/io.h"
|
||||
#include "common/jsonconfig.h"
|
||||
@@ -15,6 +16,12 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
[[gnu::cold]]
|
||||
static void printCommandFormatHelpJson(void) {
|
||||
yyjson_mut_doc* doc = yyjson_mut_doc_new(nullptr);
|
||||
@@ -432,12 +439,7 @@ static bool parseJsoncFile(FFdata* data, const char* path, yyjson_read_flag flg)
|
||||
}
|
||||
|
||||
[[gnu::cold]]
|
||||
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);
|
||||
}
|
||||
|
||||
static void setupGenConfigPath(FFdata* data, const char* filePath) {
|
||||
if (!filePath) {
|
||||
if (instance.state.platform.configDirs.length == 0) {
|
||||
fprintf(stderr, "Error: No config directory found to generate config file in. Use --gen-config <path> to specify a path\n");
|
||||
@@ -451,13 +453,23 @@ static void generateConfigFile(FFdata* data, bool force, const char* filePath, b
|
||||
} else {
|
||||
ffStrbufSetS(&data->genConfigPath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!force && ffPathExists(data->genConfigPath.chars, FF_PATHTYPE_ANY)) {
|
||||
fprintf(stderr, "Error: file `%s` exists. Use `--gen-config%s-force` to overwrite\n", data->genConfigPath.chars, fullConfig ? "-full" : "");
|
||||
[[gnu::cold]]
|
||||
static void generateConfigFile(FFdata* data, const char* filePath) {
|
||||
if (data->resultDoc) {
|
||||
fprintf(stderr, "Error: duplicated `--gen-config` or `--format json` flags found\n");
|
||||
exit(477);
|
||||
}
|
||||
|
||||
data->docType = fullConfig ? FF_RESULT_DOC_TYPE_CONFIG_FULL : FF_RESULT_DOC_TYPE_CONFIG;
|
||||
setupGenConfigPath(data, filePath);
|
||||
|
||||
if (ffPathExists(data->genConfigPath.chars, FF_PATHTYPE_ANY)) {
|
||||
fprintf(stderr, "Error: file `%s` exists. Please remove it before generating a new one\n", data->genConfigPath.chars);
|
||||
exit(477);
|
||||
}
|
||||
|
||||
data->docType = FF_RESULT_DOC_TYPE_CONFIG;
|
||||
data->resultDoc = yyjson_mut_doc_new(nullptr);
|
||||
}
|
||||
|
||||
@@ -586,6 +598,15 @@ static void enableJsonOutput(FFdata* data) {
|
||||
yyjson_mut_doc_set_root(data->resultDoc, yyjson_mut_arr(data->resultDoc));
|
||||
}
|
||||
|
||||
static void genConfigCommon(FFdata* data, const char* value) {
|
||||
if (!getenv("NO_COLOR") && isatty(STDOUT_FILENO) && isatty(STDIN_FILENO)) {
|
||||
data->genConfigInteractive = true;
|
||||
setupGenConfigPath(data, value);
|
||||
} else {
|
||||
generateConfigFile(data, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCommand(FFdata* data, char* key, char* value) {
|
||||
if (ffStrEqualsIgnCase(key, "-h") || ffStrEqualsIgnCase(key, "--help")) {
|
||||
printCommandHelp(value);
|
||||
@@ -647,13 +668,7 @@ static void parseCommand(FFdata* data, char* key, char* value) {
|
||||
|
||||
exit(0);
|
||||
} else if (ffStrEqualsIgnCase(key, "--gen-config")) {
|
||||
generateConfigFile(data, false, value, false);
|
||||
} else if (ffStrEqualsIgnCase(key, "--gen-config-force")) {
|
||||
generateConfigFile(data, true, value, false);
|
||||
} else if (ffStrEqualsIgnCase(key, "--gen-config-full")) {
|
||||
generateConfigFile(data, false, value, true);
|
||||
} else if (ffStrEqualsIgnCase(key, "--gen-config-full-force")) {
|
||||
generateConfigFile(data, true, value, true);
|
||||
genConfigCommon(data, value);
|
||||
} else if (ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--config")) {
|
||||
optionParseConfigFile(data, key, value);
|
||||
} else if (ffStrEqualsIgnCase(key, "-j") || ffStrEqualsIgnCase(key, "--json")) {
|
||||
@@ -828,6 +843,14 @@ static void writeConfigFile(FFdata* data) {
|
||||
ffOptionsGenerateLogoJsonConfig(data, &instance.config.logo);
|
||||
ffOptionsGenerateDisplayJsonConfig(data, &instance.config.display);
|
||||
ffOptionsGenerateGeneralJsonConfig(data, &instance.config.general);
|
||||
} else if (data->genConfigInteractive) {
|
||||
if (instance.config.logo.type == FF_LOGO_TYPE_NONE) {
|
||||
yyjson_mut_obj_add_null(doc, root, "logo");
|
||||
} else if (instance.config.logo.type == FF_LOGO_TYPE_SMALL) {
|
||||
yyjson_mut_val* logo = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_str(doc, logo, "type", "small");
|
||||
yyjson_mut_obj_add_val(doc, root, "logo", logo);
|
||||
}
|
||||
}
|
||||
ffMigrateCommandOptionToJsonc(data);
|
||||
|
||||
@@ -877,6 +900,14 @@ int main(int argc, char** argv) {
|
||||
if (__builtin_expect(data.genConfigPath.length == 0, true)) {
|
||||
run(&data);
|
||||
} else {
|
||||
if (data.genConfigInteractive && !ffGenConfigInteractive(&data)) {
|
||||
// User cancelled the interactive config generation
|
||||
ffStrbufDestroy(&data.structure);
|
||||
ffStrbufDestroy(&data.structureDisabled);
|
||||
yyjson_doc_free(data.configDoc);
|
||||
ffStrbufDestroy(&data.genConfigPath);
|
||||
return 0;
|
||||
}
|
||||
writeConfigFile(&data);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user