From a0c47204bb438a71cae8a7b89ef8daf1bbb48c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 26 Feb 2024 10:46:13 +0800 Subject: [PATCH] Temp: Display: support better temperature value formatting Fix #737 --- CHANGELOG.md | 13 +++ doc/json_schema.json | 41 +++++++- src/common/parsing.c | 30 +++++- src/data/help.json | 35 +++++++ src/modules/battery/battery.c | 6 +- src/modules/cpu/cpu.c | 6 +- src/modules/gpu/gpu.c | 4 +- src/modules/physicaldisk/physicaldisk.c | 6 +- src/options/display.c | 133 +++++++++++++++++------- src/options/display.h | 4 + 10 files changed, 227 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cf70d53b..80dc9de96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# 2.8.6 + +Changes: +* Due to newly introduced configs, JSONC option `{ "temperatureUnit": "C" }` has been changed to `{ "temperature": { "unit": "C" } }` + +Bugfixes: +* Fix incorrect GPU name detection for Intel iGPU on Linux (#736, GPU, Linux) + +Features: +* Support additional temperature formatting options (#737) + * `{ "temperature": { "ndigits": 1 } }` + * `{ "temperature": { "color": { "green": "green", "yellow": "yellow", "red": "red" } } }` + # 2.8.5 Bugfixes: diff --git a/doc/json_schema.json b/doc/json_schema.json index 198ec8e2c..5b7b89b7e 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -407,11 +407,42 @@ } } }, - "temperatureUnit": { - "type": "string", - "description": "Set the unit of the temperature", - "enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"], - "default": "C" + "temperature": { + "type": "object", + "description": "Set how a temperature value should be displayed", + "properties": { + "unit": { + "type": "string", + "description": "Set the unit of the temperature", + "enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"], + "default": "C" + }, + "ndigits": { + "type": "integer", + "description": "Set the number of digits to keep after the decimal point when formatting temperature values", + "minimum": 0, + "maximum": 9, + "default": 1 + }, + "color": { + "type": "object", + "description": "Set color used in different states of temperature values", + "properties": { + "green": { + "description": "Color used in green state", + "$ref": "#/$defs/colors" + }, + "yellow": { + "description": "Color used in yellow state", + "$ref": "#/$defs/colors" + }, + "red": { + "description": "Color used in red state", + "$ref": "#/$defs/colors" + } + } + } + } }, "bar": { "type": "object", diff --git a/src/common/parsing.c b/src/common/parsing.c index 5f5b18d04..f4833fd35 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -1,5 +1,6 @@ #include "fastfetch.h" #include "common/parsing.h" +#include "util/textModifier.h" #include #include @@ -98,18 +99,39 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result) void ffParseTemperature(double celsius, FFstrbuf* buffer) { - switch (instance.config.display.temperatureUnit) + if (celsius != celsius) // ignores NaN + return; + + const FFOptionsDisplay* options = &instance.config.display; + const char* colorGreen = options->temperatureColorGreen.chars; + const char* colorYellow = options->temperatureColorYellow.chars; + const char* colorRed = options->temperatureColorRed.chars; + + if (!options->pipe) + { + if (celsius < 50) + ffStrbufAppendF(buffer, "\e[%sm", colorGreen); + else if (celsius < 80) + ffStrbufAppendF(buffer, "\e[%sm", colorYellow); + else + ffStrbufAppendF(buffer, "\e[%sm", colorRed); + } + + switch (options->temperatureUnit) { case FF_TEMPERATURE_UNIT_CELSIUS: - ffStrbufAppendF(buffer, "%.1f°C", celsius); + ffStrbufAppendF(buffer, "%.*f°C", options->temperatureNdigits, celsius); break; case FF_TEMPERATURE_UNIT_FAHRENHEIT: - ffStrbufAppendF(buffer, "%.1f°F", celsius * 1.8 + 32); + ffStrbufAppendF(buffer, "%.*f°F", options->temperatureNdigits, celsius * 1.8 + 32); break; case FF_TEMPERATURE_UNIT_KELVIN: - ffStrbufAppendF(buffer, "%.1f K", celsius + 273.15); + ffStrbufAppendF(buffer, "%.*f K", options->temperatureNdigits, celsius + 273.15); break; } + + if (!options->pipe) + ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); } void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4) diff --git a/src/data/help.json b/src/data/help.json index 752295eec..5199b1b42 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -667,6 +667,41 @@ }, "default": "C" } + }, + { + "long": "temperature-ndigits", + "desc": "Set the number of digits to keep after the decimal point when printing temperature", + "arg": { + "type": "num", + "default": 2 + } + }, + { + "long": "temperature-color-green", + "desc": "Set color used in green state of temperature values", + "remark": "See `-h color` for the list of available colors", + "arg": { + "type": "color", + "default": "green" + } + }, + { + "long": "temperature-color-yellow", + "desc": "Set color used in yellow state of temperature values", + "remark": "See `-h color` for the list of available colors", + "arg": { + "type": "color", + "default": "light_yellow" + } + }, + { + "long": "temperature-color-red", + "desc": "Set color used in red state of temperature values", + "remark": "See `-h color` for the list of available colors", + "arg": { + "type": "color", + "default": "light_red" + } } ], "Library path": [ diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index a97dd263b..bab7d5db0 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -58,13 +58,15 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin { FF_STRBUF_AUTO_DESTROY capacityStr = ffStrbufCreate(); ffPercentAppendNum(&capacityStr, result->capacity, options->percent, false); + FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); + ffParseTemperature(result->temperature, &tempStr); ffPrintFormat(FF_BATTERY_MODULE_NAME, index, &options->moduleArgs, FF_BATTERY_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->technology}, {FF_FORMAT_ARG_TYPE_STRBUF, &capacityStr}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->status}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature}, + {FF_FORMAT_ARG_TYPE_STRBUF, &tempStr}, {FF_FORMAT_ARG_TYPE_UINT, &result->cycleCount}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->serial}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->manufactureDate}, @@ -226,7 +228,7 @@ void ffPrintBatteryHelpFormat(void) "Battery technology", "Battery capacity (percentage)", "Battery status", - "Battery temperature", + "Battery temperature (formatted)", "Battery cycle count", "Battery serial number", "Battery manufactor date", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index f1ee0e84f..c2716b528 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -60,6 +60,8 @@ void ffPrintCPU(FFCPUOptions* options) } else { + FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); + ffParseTemperature(cpu.temperature, &tempStr); ffPrintFormat(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_CPU_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &cpu.name}, {FF_FORMAT_ARG_TYPE_STRBUF, &cpu.vendor}, @@ -68,7 +70,7 @@ void ffPrintCPU(FFCPUOptions* options) {FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline}, {FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyMin}, {FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyMax}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.temperature} + {FF_FORMAT_ARG_TYPE_STRBUF, &tempStr} }); } } @@ -193,7 +195,7 @@ void ffPrintCPUHelpFormat(void) "Online core count", "Min frequency", "Max frequency", - "Temperature" + "Temperature (formatted)" }); } diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index b8c3118a4..270872127 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -72,11 +72,13 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu } else { + FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); + ffParseTemperature(gpu->temperature, &tempStr); ffPrintFormat(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor}, {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}, + {FF_FORMAT_ARG_TYPE_STRBUF, &tempStr}, {FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount}, {FF_FORMAT_ARG_TYPE_STRING, type}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.total}, diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 864f5a673..01f5033c5 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -102,6 +102,8 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) } else { + FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); + ffParseTemperature(dev->temperature, &tempStr); if (dev->type & FF_PHYSICALDISK_TYPE_READWRITE) readOnlyType = "Read-write"; ffParseSize(dev->size, &buffer); @@ -115,7 +117,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) {FF_FORMAT_ARG_TYPE_STRING, removableType}, {FF_FORMAT_ARG_TYPE_STRING, readOnlyType}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->revision}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &dev->temperature}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &tempStr}, }); } ++index; @@ -263,7 +265,7 @@ void ffPrintPhysicalDiskHelpFormat(void) "Device kind (Removable or Fixed)", "Device kind (Read-only or Read-write)", "Product revision", - "Device temperature", + "Device temperature (formatted)", }); } diff --git a/src/options/display.c b/src/options/display.c index c1b254b5d..7adccaa8c 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -94,20 +94,46 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); if (ndigits) options->percentNdigits = (uint8_t) yyjson_get_uint(ndigits); } - else if (ffStrEqualsIgnCase(key, "temperatureUnit")) + else if (ffStrEqualsIgnCase(key, "temperature")) { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, - { "C", FF_TEMPERATURE_UNIT_CELSIUS }, - { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, - { "K", FF_TEMPERATURE_UNIT_KELVIN }, - {}, - }); - if (error) return error; - options->temperatureUnit = (FFTemperatureUnit) value; + if (!yyjson_is_obj(val)) + return "display.temperature must be an object"; + + yyjson_val* unit = yyjson_obj_get(val, "unit"); + if (unit) + { + int value; + const char* error = ffJsonConfigParseEnum(unit, &value, (FFKeyValuePair[]) { + { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, + { "C", FF_TEMPERATURE_UNIT_CELSIUS }, + { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, + { "K", FF_TEMPERATURE_UNIT_KELVIN }, + {}, + }); + if (error) return error; + options->temperatureUnit = (FFTemperatureUnit) value; + } + + yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); + if (ndigits) options->temperatureNdigits = (uint8_t) yyjson_get_uint(ndigits); + + yyjson_val* color = yyjson_obj_get(val, "color"); + if (color) + { + if (!yyjson_is_obj(color)) + return "display.temperature.color must be an object"; + + yyjson_val* green = yyjson_obj_get(color, "green"); + if (green) ffOptionParseColor(yyjson_get_str(green), &options->temperatureColorGreen); + + yyjson_val* yellow = yyjson_obj_get(color, "yellow"); + if (yellow) ffOptionParseColor(yyjson_get_str(yellow), &options->temperatureColorYellow); + + yyjson_val* red = yyjson_obj_get(color, "red"); + if (red) ffOptionParseColor(yyjson_get_str(red), &options->temperatureColorRed); + } } else if (ffStrEqualsIgnCase(key, "percent")) { @@ -253,17 +279,31 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key {} }); } - else if(ffStrEqualsIgnCase(key, "--temperature-unit")) + else if(ffStrStartsWithIgnCase(key, "--temperature-")) { - options->temperatureUnit = (FFTemperatureUnit) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, - { "C", FF_TEMPERATURE_UNIT_CELSIUS }, - { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, - { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, - { "K", FF_TEMPERATURE_UNIT_KELVIN }, - {}, - }); + const char* subkey = key + strlen("--temperature-"); + if(ffStrEqualsIgnCase(subkey, "unit")) + { + options->temperatureUnit = (FFTemperatureUnit) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS }, + { "C", FF_TEMPERATURE_UNIT_CELSIUS }, + { "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "F", FF_TEMPERATURE_UNIT_FAHRENHEIT }, + { "KELVIN", FF_TEMPERATURE_UNIT_KELVIN }, + { "K", FF_TEMPERATURE_UNIT_KELVIN }, + {}, + }); + } + else if (ffStrEqualsIgnCase(subkey, "ndigits")) + options->temperatureNdigits = (uint8_t) ffOptionParseUInt32(key, value); + else if(ffStrEqualsIgnCase(subkey, "color-green")) + ffOptionParseColor(value, &options->temperatureColorGreen); + else if(ffStrEqualsIgnCase(subkey, "color-yellow")) + ffOptionParseColor(value, &options->temperatureColorYellow); + else if(ffStrEqualsIgnCase(subkey, "color-red")) + ffOptionParseColor(value, &options->temperatureColorRed); + else + return false; } else if(ffStrStartsWithIgnCase(key, "--percent-")) { @@ -323,11 +363,16 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) options->binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC; options->sizeNdigits = 2; options->sizeMaxPrefix = UINT8_MAX; - options->temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS; options->stat = false; options->noBuffer = false; options->keyWidth = 0; + options->temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS; + options->temperatureNdigits = 1; + ffStrbufInitStatic(&options->temperatureColorGreen, FF_COLOR_FG_GREEN); + ffStrbufInitStatic(&options->temperatureColorYellow, FF_COLOR_FG_LIGHT_YELLOW); + ffStrbufInitStatic(&options->temperatureColorRed, FF_COLOR_FG_LIGHT_RED); + ffStrbufInitStatic(&options->barCharElapsed, "■"); ffStrbufInitStatic(&options->barCharTotal, "-"); options->barWidth = 10; @@ -430,20 +475,38 @@ void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_do yyjson_mut_obj_add_val(doc, obj, "size", size); } - if (options->temperatureUnit != defaultOptions.temperatureUnit) { - switch (options->temperatureUnit) + yyjson_mut_val* temperature = yyjson_mut_obj(doc); + if (options->temperatureUnit != defaultOptions.temperatureUnit) { - case FF_TEMPERATURE_UNIT_CELSIUS: - yyjson_mut_obj_add_str(doc, obj, "temperatureUnit", "C"); - break; - case FF_TEMPERATURE_UNIT_FAHRENHEIT: - yyjson_mut_obj_add_str(doc, obj, "temperatureUnit", "F"); - break; - case FF_TEMPERATURE_UNIT_KELVIN: - yyjson_mut_obj_add_str(doc, obj, "temperatureUnit", "K"); - break; + switch (options->temperatureUnit) + { + case FF_TEMPERATURE_UNIT_CELSIUS: + yyjson_mut_obj_add_str(doc, obj, "unit", "C"); + break; + case FF_TEMPERATURE_UNIT_FAHRENHEIT: + yyjson_mut_obj_add_str(doc, obj, "unit", "F"); + break; + case FF_TEMPERATURE_UNIT_KELVIN: + yyjson_mut_obj_add_str(doc, obj, "unit", "K"); + break; + } } + if (options->temperatureNdigits != defaultOptions.temperatureNdigits) + yyjson_mut_obj_add_uint(doc, temperature, "ndigits", options->temperatureNdigits); + { + yyjson_mut_val* color = yyjson_mut_obj(doc); + if (!ffStrbufEqual(&options->temperatureColorGreen, &defaultOptions.temperatureColorGreen)) + yyjson_mut_obj_add_strbuf(doc, color, "green", &options->temperatureColorGreen); + if (!ffStrbufEqual(&options->temperatureColorYellow, &defaultOptions.temperatureColorYellow)) + yyjson_mut_obj_add_strbuf(doc, color, "yellow", &options->temperatureColorYellow); + if (!ffStrbufEqual(&options->temperatureColorRed, &defaultOptions.temperatureColorRed)) + yyjson_mut_obj_add_strbuf(doc, color, "red", &options->temperatureColorRed); + if (yyjson_mut_obj_size(color) > 0) + yyjson_mut_obj_add_val(doc, temperature, "color", color); + } + if (yyjson_mut_obj_size(temperature) > 0) + yyjson_mut_obj_add_val(doc, obj, "temperature", temperature); } { diff --git a/src/options/display.h b/src/options/display.h index 296e95a24..2d800150e 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -35,6 +35,10 @@ typedef struct FFOptionsDisplay uint8_t sizeNdigits; uint8_t sizeMaxPrefix; FFTemperatureUnit temperatureUnit; + uint8_t temperatureNdigits; + FFstrbuf temperatureColorGreen; + FFstrbuf temperatureColorYellow; + FFstrbuf temperatureColorRed; FFstrbuf barCharElapsed; FFstrbuf barCharTotal; uint8_t barWidth;