diff --git a/doc/json_schema.json b/doc/json_schema.json index ce00756da..884fd4c2e 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -26,6 +26,24 @@ "format": { "description": "Output format of the module", "type": "string" + }, + "percent": { + "description": "Threshold of percentage colors", + "type": "object", + "properties": { + "green": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "Value less then green will be shown in green" + }, + "yellow": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "Value greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red" + } + } } }, "type": "object", @@ -672,10 +690,6 @@ "const": "font", "description": "Print system font name" }, - { - "const": "gamepad", - "description": "List connected gamepads" - }, { "const": "host", "description": "Print product name of your computer" @@ -700,10 +714,6 @@ "const": "media", "description": "Print playing song name" }, - { - "const": "memory", - "description": "Print system memory usage info" - }, { "const": "monitor", "description": "Print connected physical monitor information" @@ -732,10 +742,6 @@ "const": "shell", "description": "Print current shell name and version" }, - { - "const": "swap", - "description": "Print swap (paging file) space usage" - }, { "const": "terminal", "description": "Print current terminal name and version" @@ -814,6 +820,9 @@ "type": "boolean", "default": false }, + "percent": { + "$ref": "#/$defs/percent" + }, "key": { "$ref": "#/$defs/key" }, @@ -841,6 +850,9 @@ "type": "boolean", "default": false }, + "percent": { + "$ref": "#/$defs/percent" + }, "key": { "$ref": "#/$defs/key" }, @@ -863,6 +875,9 @@ "const": "brightness", "description": "Print current brightness level of your monitors" }, + "percent": { + "$ref": "#/$defs/percent" + }, "ddcciSleep": { "type": "integer", "description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee for detail", @@ -934,6 +949,9 @@ "const": "cpuusage", "description": "Print CPU usage. Costs some time to collect data" }, + "percent": { + "$ref": "#/$defs/percent" + }, "separate": { "type": "boolean", "description": "Display CPU usage per CPU logical core, instead of an average result", @@ -1103,6 +1121,9 @@ "description": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes", "default": false }, + "percent": { + "$ref": "#/$defs/percent" + }, "key": { "$ref": "#/$defs/key" }, @@ -1170,6 +1191,31 @@ } } }, + { + "title": "Gamepad", + "properties": { + "type": { + "const": "gamepad", + "description": "List connected gamepads" + }, + "percent": { + "$ref": "#/$defs/percent" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "GPU", "properties": { @@ -1272,6 +1318,31 @@ }, "additionalProperties": false }, + { + "title": "Memory", + "properties": { + "type": { + "const": "memory", + "description": "Print system memory usage info" + }, + "percent": { + "$ref": "#/$defs/percent" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "NetIO", "properties": { @@ -1458,6 +1529,34 @@ ], "default": "main" }, + "percent": { + "$ref": "#/$defs/percent" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, + { + "title": "Swap", + "properties": { + "type": { + "const": "swap", + "description": "Print swap (paging file) space usage" + }, + "percent": { + "$ref": "#/$defs/percent" + }, "key": { "$ref": "#/$defs/key" }, diff --git a/src/common/percent.c b/src/common/percent.c index 0dff8b169..0b154e744 100644 --- a/src/common/percent.c +++ b/src/common/percent.c @@ -1,7 +1,10 @@ #include "fastfetch.h" #include "common/percent.h" #include "common/color.h" +#include "common/option.h" +#include "common/jsonconfig.h" #include "util/textModifier.h" +#include "util/stringUtils.h" void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config) { @@ -103,3 +106,87 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config if (parentheses) ffStrbufAppendC(buffer, ')'); } + +bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config) +{ + if (!ffStrStartsWithIgnCase(subkey, "percent-")) + return false; + + subkey += strlen("percent-"); + + if (ffStrEqualsIgnCase(subkey, "green")) + { + uint32_t num = ffOptionParseUInt32(key, value); + if (num > 100) + { + fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key); + exit(480); + } + config->green = (uint8_t) num; + return true; + } + + if (ffStrEqualsIgnCase(subkey, "yellow")) + { + uint32_t num = ffOptionParseUInt32(key, value); + if (num > 100) + { + fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key); + exit(480); + } + config->yellow = (uint8_t) num; + return true; + } + + return false; +} + +bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config) +{ + if (!ffStrEqualsIgnCase(key, "percent")) + return false; + + if (!yyjson_is_obj(value)) + { + fprintf(stderr, "Error: usage: %s must be an object\n", key); + exit(480); + } + + yyjson_val* greenVal = yyjson_obj_get(value, "green"); + if (greenVal) + { + int num = yyjson_get_int(greenVal); + if (num < 0 || num > 100) + { + fputs("Error: usage: percent.green must be between 0 and 100\n", stderr); + exit(480); + } + config->green = (uint8_t) num; + } + + yyjson_val* yellowVal = yyjson_obj_get(value, "yellow"); + if (yellowVal) + { + int num = yyjson_get_int(yellowVal); + if (num < 0 || num > 100) + { + fputs("Error: usage: percent.yellow must be between 0 and 100\n", stderr); + exit(480); + } + config->yellow = (uint8_t) num; + } + + return true; +} + +void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config) +{ + if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow) + return; + + yyjson_mut_val* percent = yyjson_mut_obj_add_obj(doc, module, "percent"); + if (config.green != defaultConfig.green) + yyjson_mut_obj_add_uint(doc, percent, "green", config.green); + if (config.yellow != defaultConfig.yellow) + yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow); +} diff --git a/src/common/percent.h b/src/common/percent.h index 190c8a374..e3e83b4a4 100644 --- a/src/common/percent.h +++ b/src/common/percent.h @@ -28,3 +28,10 @@ typedef struct FFPercentConfig void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config); void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses); + +typedef struct yyjson_val yyjson_val; +typedef struct yyjson_mut_doc yyjson_mut_doc; +typedef struct yyjson_mut_val yyjson_mut_val; +bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config); +bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config); +void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config); diff --git a/src/data/help.json b/src/data/help.json index d3da78a82..c22c42ef5 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1351,6 +1351,29 @@ "type": "num" }, "pseudo": true + }, + { + "long": "-percent-green", + "desc": [ + "Threshold of percentage colors", + "Value less then percent-green will be shown in green" + ], + "arg": { + "type": "num" + }, + "pseudo": true + }, + { + "long": "-percent-yellow", + "desc": [ + "Threshold of percentage colors", + "Value greater than percent-green and less then yellow will be shown in yellow", + "Value greater than percent-yellow will be shown in red" + ], + "arg": { + "type": "num" + }, + "pseudo": true } ] } diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index d667ea846..a97dd263b 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -122,6 +122,9 @@ bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, co } #endif + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -152,6 +155,9 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -170,6 +176,8 @@ void ffGenerateBatteryJsonConfig(FFBatteryOptions* options, yyjson_mut_doc* doc, if (options->temp != defaultOptions.temp) yyjson_mut_obj_add_bool(doc, module, "temp", options->temp); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index cd0692746..20bb9707c 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -93,6 +93,9 @@ bool ffParseBluetoothCommandOptions(FFBluetoothOptions* options, const char* key return true; } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -115,6 +118,9 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -128,6 +134,8 @@ void ffGenerateBluetoothJsonConfig(FFBluetoothOptions* options, yyjson_mut_doc* if (options->showDisconnected != defaultOptions.showDisconnected) yyjson_mut_obj_add_bool(doc, module, "showDisconnected", options->showDisconnected); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 4dd295a36..49283474f 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -97,6 +97,9 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k return true; } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -119,6 +122,9 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -132,6 +138,8 @@ void ffGenerateBrightnessJsonConfig(FFBrightnessOptions* options, yyjson_mut_doc if (defaultOptions.ddcciSleep != options->ddcciSleep) yyjson_mut_obj_add_uint(doc, module, "ddcciSleep", options->ddcciSleep); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 38738fabb..e8787dd33 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -102,6 +102,9 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, return true; } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -124,6 +127,9 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -137,6 +143,8 @@ void ffGenerateCPUUsageJsonConfig(FFCPUUsageOptions* options, yyjson_mut_doc* do if (options->separate != defaultOptions.separate) yyjson_mut_obj_add_bool(doc, module, "separate", options->separate); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateCPUUsageJsonResult(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index fae7e3501..a874cc892 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -278,6 +278,9 @@ bool ffParseDiskCommandOptions(FFDiskOptions* options, const char* key, const ch return true; } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -354,6 +357,9 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -388,6 +394,8 @@ void ffGenerateDiskJsonConfig(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso if (defaultOptions.calcType != options->calcType) yyjson_mut_obj_add_bool(doc, module, "useAvailable", options->calcType == FF_DISK_CALC_TYPE_AVAILABLE); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 76de33845..2c5341333 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -70,6 +70,9 @@ bool ffParseGamepadCommandOptions(FFGamepadOptions* options, const char* key, co if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -86,6 +89,9 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -96,6 +102,8 @@ void ffGenerateGamepadJsonConfig(FFGamepadOptions* options, yyjson_mut_doc* doc, ffInitGamepadOptions(&defaultOptions); ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index f1b348d18..b8c3118a4 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -162,6 +162,9 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char }); } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -212,6 +215,9 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -247,6 +253,8 @@ void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ break; } } + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index c71ca9167..485b62130 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -73,6 +73,9 @@ bool ffParseMemoryCommandOptions(FFMemoryOptions* options, const char* key, cons if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -89,6 +92,9 @@ void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -99,6 +105,8 @@ void ffGenerateMemoryJsonConfig(FFMemoryOptions* options, yyjson_mut_doc* doc, y ffInitMemoryOptions(&defaultOptions); ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateMemoryJsonResult(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index d7fbebf99..0d0950011 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -121,6 +121,9 @@ bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const return true; } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -153,6 +156,9 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) continue; } + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -179,6 +185,8 @@ void ffGenerateSoundJsonConfig(FFSoundOptions* options, yyjson_mut_doc* doc, yyj break; } } + + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index b4103bf6b..bf7c7481a 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -82,6 +82,9 @@ bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const ch if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) + return true; + return false; } @@ -98,6 +101,9 @@ void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffPercentParseJsonObject(key, val, &options->percent)) + continue; + ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -107,6 +113,8 @@ void ffGenerateSwapJsonConfig(FFSwapOptions* options, yyjson_mut_doc* doc, yyjso __attribute__((__cleanup__(ffDestroySwapOptions))) FFSwapOptions defaultOptions; ffInitSwapOptions(&defaultOptions); + ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); }