From 738daa1c7770f1935d898e6c37c901003b0fae7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 8 May 2024 16:41:33 +0800 Subject: [PATCH] Loadavg: new module --- CMakeLists.txt | 8 +- doc/json_schema.json | 27 +++++ src/common/modules.c | 1 + src/detection/loadavg/loadavg.h | 5 + src/detection/loadavg/loadavg_linux.c | 8 ++ src/detection/loadavg/loadavg_nosupport.c | 6 ++ src/modules/loadavg/loadavg.c | 114 ++++++++++++++++++++++ src/modules/loadavg/loadavg.h | 9 ++ src/modules/loadavg/option.h | 11 +++ src/modules/modules.h | 1 + src/modules/options.h | 1 + src/options/modules.c | 2 + src/options/modules.h | 1 + 13 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/detection/loadavg/loadavg.h create mode 100644 src/detection/loadavg/loadavg_linux.c create mode 100644 src/detection/loadavg/loadavg_nosupport.c create mode 100644 src/modules/loadavg/loadavg.c create mode 100644 src/modules/loadavg/loadavg.h create mode 100644 src/modules/loadavg/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 89649978b..031b20422 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -334,6 +334,7 @@ set(LIBFASTFETCH_SRC src/modules/gamepad/gamepad.c src/modules/kernel/kernel.c src/modules/lm/lm.c + src/modules/loadavg/loadavg.c src/modules/locale/locale.c src/modules/localip/localip.c src/modules/memory/memory.c @@ -417,6 +418,7 @@ if(LINUX) src/detection/icons/icons_linux.c src/detection/libc/libc_linux.c src/detection/lm/lm_linux.c + src/detection/loadavg/loadavg_linux.c src/detection/locale/locale_linux.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_linux.c @@ -472,6 +474,7 @@ elseif(ANDROID) src/detection/icons/icons_nosupport.c src/detection/libc/libc_android.c src/detection/lm/lm_nosupport.c + src/detection/loadavg/loadavg_linux.c src/detection/locale/locale_linux.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_nosupport.c @@ -538,6 +541,7 @@ elseif(BSD) src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c src/detection/libc/libc_bsd.c + src/detection/loadavg/loadavg_linux.c src/detection/locale/locale_linux.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_bsd.c @@ -592,8 +596,9 @@ elseif(APPLE) src/detection/gpu/gpu_apple.c src/detection/gpu/gpu_apple.m src/detection/host/host_apple.c - src/detection/lm/lm_nosupport.c src/detection/icons/icons_nosupport.c + src/detection/lm/lm_nosupport.c + src/detection/loadavg/loadavg_linux.c src/detection/libc/libc_apple.c src/detection/locale/locale_linux.c src/detection/localip/localip_linux.c @@ -651,6 +656,7 @@ elseif(WIN32) src/detection/icons/icons_windows.c src/detection/libc/libc_windows.cpp src/detection/lm/lm_nosupport.c + src/detection/loadavg/loadavg_nosupport.c src/detection/locale/locale_windows.c src/detection/localip/localip_windows.c src/detection/gamepad/gamepad_windows.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 82ab9c5f0..ef71c7bda 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -702,6 +702,7 @@ "icons", "kernel", "lm", + "loadavg", "locale", "localip", "media", @@ -1555,6 +1556,32 @@ } } }, + { + "title": "Loadavg", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "const": "loadavg", + "description": "Print system load averages" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + } + }, { "title": "NetIO", "type": "object", diff --git a/src/common/modules.c b/src/common/modules.c index 718a8114a..1c4d43e4f 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -71,6 +71,7 @@ static FFModuleBaseInfo* K[] = { static FFModuleBaseInfo* L[] = { (void*) &instance.config.modules.lm, + (void*) &instance.config.modules.loadavg, (void*) &instance.config.modules.locale, (void*) &instance.config.modules.localIP, NULL, diff --git a/src/detection/loadavg/loadavg.h b/src/detection/loadavg/loadavg.h new file mode 100644 index 000000000..4cfa696ed --- /dev/null +++ b/src/detection/loadavg/loadavg.h @@ -0,0 +1,5 @@ +#pragma once + +#include "fastfetch.h" + +const char* ffDetectLoadavg(double result[3]); diff --git a/src/detection/loadavg/loadavg_linux.c b/src/detection/loadavg/loadavg_linux.c new file mode 100644 index 000000000..69a38e7db --- /dev/null +++ b/src/detection/loadavg/loadavg_linux.c @@ -0,0 +1,8 @@ +#include "detection/loadavg/loadavg.h" + +#include + +const char* ffDetectLoadavg(double result[3]) +{ + return getloadavg(result, 3) < 0 ? "getloadavg() failed" : NULL; +} diff --git a/src/detection/loadavg/loadavg_nosupport.c b/src/detection/loadavg/loadavg_nosupport.c new file mode 100644 index 000000000..2d51217a5 --- /dev/null +++ b/src/detection/loadavg/loadavg_nosupport.c @@ -0,0 +1,6 @@ +#include "detection/loadavg/loadavg.h" + +const char* ffDetectLoadavg(FF_MAYBE_UNUSED double result[3]) +{ + return "Not supported on this platform"; +} diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c new file mode 100644 index 000000000..4cba6f93d --- /dev/null +++ b/src/modules/loadavg/loadavg.c @@ -0,0 +1,114 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/loadavg/loadavg.h" +#include "modules/loadavg/loadavg.h" +#include "util/stringUtils.h" + +#define FF_LOADAVG_NUM_FORMAT_ARGS 3 + +void ffPrintLoadavg(FFLoadavgOptions* options) +{ + double result[3] = { 0.0 / 0.0, 0.0 / 0.0, 0.0 / 0.0 }; + + const char* error = ffDetectLoadavg(result); + if(error) + { + ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + printf("%.2f, %.2f, %.2f\n", result[0], result[1], result[2]); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_LOADAVG_NUM_FORMAT_ARGS, ((FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_DOUBLE, &result[0]}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &result[1]}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &result[2]}, + })); + } +} + +bool ffParseLoadavgCommandOptions(FFLoadavgOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_LOADAVG_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateLoadavgJsonConfig(FFLoadavgOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyLoadavgOptions))) FFLoadavgOptions defaultOptions; + ffInitLoadavgOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateLoadavgJsonResult(FF_MAYBE_UNUSED FFLoadavgOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + double result[3] = { 0.0 / 0.0, 0.0 / 0.0, 0.0 / 0.0 }; + + const char* error = ffDetectLoadavg(result); + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + for (size_t i = 0; i < 3; i++) + yyjson_mut_arr_add_real(doc, arr, result[i]); +} + +void ffPrintLoadavgHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_LOADAVG_MODULE_NAME, "{1}, {2}, {3}", FF_LOADAVG_NUM_FORMAT_ARGS, ((const char* []) { + "Load average over 1min", + "Load average over 5min", + "Load average over 15min", + })); +} + +void ffInitLoadavgOptions(FFLoadavgOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_LOADAVG_MODULE_NAME, + "Print system load averages", + ffParseLoadavgCommandOptions, + ffParseLoadavgJsonObject, + ffPrintLoadavg, + ffGenerateLoadavgJsonResult, + ffPrintLoadavgHelpFormat, + ffGenerateLoadavgJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs); +} + +void ffDestroyLoadavgOptions(FFLoadavgOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/loadavg/loadavg.h b/src/modules/loadavg/loadavg.h new file mode 100644 index 000000000..1d546f57b --- /dev/null +++ b/src/modules/loadavg/loadavg.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_LOADAVG_MODULE_NAME "Loadavg" + +void ffPrintLoadavg(FFLoadavgOptions* options); +void ffInitLoadavgOptions(FFLoadavgOptions* options); +void ffDestroyLoadavgOptions(FFLoadavgOptions* options); diff --git a/src/modules/loadavg/option.h b/src/modules/loadavg/option.h new file mode 100644 index 000000000..d61f04d7c --- /dev/null +++ b/src/modules/loadavg/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFLoadavgOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFLoadavgOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 84c7f9dec..cfff529c9 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -28,6 +28,7 @@ #include "modules/icons/icons.h" #include "modules/kernel/kernel.h" #include "modules/lm/lm.h" +#include "modules/loadavg/loadavg.h" #include "modules/locale/locale.h" #include "modules/localip/localip.h" #include "modules/media/media.h" diff --git a/src/modules/options.h b/src/modules/options.h index 1e998396a..af4ec7e99 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -27,6 +27,7 @@ #include "modules/gpu/option.h" #include "modules/icons/option.h" #include "modules/kernel/option.h" +#include "modules/loadavg/option.h" #include "modules/locale/option.h" #include "modules/lm/option.h" #include "modules/localip/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index 0de31e727..a64ca5ef9 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -29,6 +29,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitIconsOptions(&options->icons); ffInitKernelOptions(&options->kernel); ffInitLMOptions(&options->lm); + ffInitLoadavgOptions(&options->loadavg); ffInitLocalIpOptions(&options->localIP); ffInitLocaleOptions(&options->locale); ffInitMediaOptions(&options->media); @@ -93,6 +94,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyIconsOptions(&options->icons); ffDestroyKernelOptions(&options->kernel); ffDestroyLMOptions(&options->lm); + ffDestroyLoadavgOptions(&options->loadavg); ffDestroyLocalIpOptions(&options->localIP); ffDestroyLocaleOptions(&options->locale); ffDestroyMediaOptions(&options->media); diff --git a/src/options/modules.h b/src/options/modules.h index 7c19db986..d04f65071 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -30,6 +30,7 @@ typedef struct FFOptionsModules FFIconsOptions icons; FFKernelOptions kernel; FFLMOptions lm; + FFLoadavgOptions loadavg; FFLocalIpOptions localIP; FFLocaleOptions locale; FFMediaOptions media;