From a0174e86660dbefed66fefbaae95f79a06a98b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Jul 2025 14:30:36 +0800 Subject: [PATCH] Global: add new unit related options 1. `---space-before-unit` 2. `--duration-abbreviation` 3. various code refactoring and cleanups --- CMakeLists.txt | 5 +- doc/json_schema.json | 44 ++++++ src/common/duration.c | 87 ++++++++++++ src/common/duration.h | 3 + src/common/frequency.c | 17 +++ src/common/frequency.h | 3 + src/common/parsing.c | 106 --------------- src/common/parsing.h | 4 - src/common/percent.c | 4 +- src/common/size.c | 42 ++++++ src/common/size.h | 3 + src/common/temps.c | 9 +- src/data/help.json | 73 +++++++++- src/modules/battery/battery.c | 4 +- src/modules/btrfs/btrfs.c | 11 +- src/modules/cpu/cpu.c | 7 +- src/modules/cpucache/cpucache.c | 9 +- src/modules/disk/disk.c | 6 +- src/modules/diskio/diskio.c | 10 +- src/modules/display/display.c | 11 +- src/modules/gpu/gpu.c | 19 +-- src/modules/kernel/kernel.c | 3 +- src/modules/memory/memory.c | 6 +- src/modules/netio/netio.c | 10 +- src/modules/physicaldisk/physicaldisk.c | 4 +- src/modules/physicalmemory/physicalmemory.c | 4 +- src/modules/swap/swap.c | 6 +- src/modules/uptime/uptime.c | 3 +- src/modules/wifi/wifi.c | 5 +- src/modules/zpool/zpool.c | 5 +- src/options/display.c | 140 ++++++++++++++++++++ src/options/display.h | 14 ++ tests/duration.c | 53 +++++++- 33 files changed, 556 insertions(+), 174 deletions(-) create mode 100644 src/common/duration.c create mode 100644 src/common/duration.h create mode 100644 src/common/frequency.c create mode 100644 src/common/frequency.h create mode 100644 src/common/size.c create mode 100644 src/common/size.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e008886a7..f66e830c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,10 +351,11 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}") ####################### set(LIBFASTFETCH_SRC - src/common/percent.c src/common/commandoption.c + src/common/duration.c src/common/font.c src/common/format.c + src/common/frequency.c src/common/init.c src/common/jsonconfig.c src/common/library.c @@ -363,9 +364,11 @@ set(LIBFASTFETCH_SRC src/common/networking/networking_common.c src/common/option.c src/common/parsing.c + src/common/percent.c src/common/printing.c src/common/properties.c src/common/settings.c + src/common/size.c src/common/temps.c src/detection/bluetoothradio/bluetoothradio.c src/detection/bootmgr/bootmgr.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 80924361c..ffc056d75 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -232,6 +232,24 @@ } } }, + "spaceBeforeUnit": { + "type": "string", + "description": "Whether to put a space before the unit", + "oneOf": [ + { + "const": "default", + "description": "Use the default behavior of the module" + }, + { + "const": "always", + "description": "Always add a space before the unit" + }, + { + "const": "never", + "description": "Never add a space before the unit" + } + ] + }, "batteryFormat": { @@ -923,6 +941,9 @@ "minimum": 0, "maximum": 9, "default": 2 + }, + "spaceBeforeUnit": { + "$ref": "#/$defs/spaceBeforeUnit" } } }, @@ -965,6 +986,9 @@ "default": "light_red" } } + }, + "spaceBeforeUnit": { + "$ref": "#/$defs/spaceBeforeUnit" } } }, @@ -1037,6 +1061,9 @@ "default": "light_red" } } + }, + "spaceBeforeUnit": { + "$ref": "#/$defs/spaceBeforeUnit" } } }, @@ -1051,6 +1078,23 @@ "minimum": -1, "maximum": 9, "default": 2 + }, + "spaceBeforeUnit": { + "$ref": "#/$defs/spaceBeforeUnit" + } + } + }, + "duration": { + "type": "object", + "description": "Set how duration values should be displayed", + "properties": { + "abbreviation": { + "type": "boolean", + "description": "Set whether to abbreviate duration values\nIf true, the output will be in the form of \"1h 2m\" instead of \"1 hour, 2 mins\"", + "default": false + }, + "spaceBeforeUnit": { + "$ref": "#/$defs/spaceBeforeUnit" } } }, diff --git a/src/common/duration.c b/src/common/duration.c new file mode 100644 index 000000000..16e5570e9 --- /dev/null +++ b/src/common/duration.c @@ -0,0 +1,87 @@ +#include "duration.h" + +void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result) +{ + const FFOptionsDisplay* options = &instance.config.display; + + const char* space = instance.config.display.durationSpaceBeforeUnit != FF_SPACE_BEFORE_UNIT_NEVER ? " " : ""; + + if(totalSeconds < 60) + { + ffStrbufAppendF(result, options->durationAbbreviation ? "%u%ssec" : "%u%ssecond", (unsigned) totalSeconds, space); + if (totalSeconds != 1) + ffStrbufAppendC(result, 's'); + return; + } + + uint32_t seconds = (uint32_t) (totalSeconds % 60); + totalSeconds /= 60; + if (seconds >= 30) + totalSeconds++; + + uint32_t minutes = (uint32_t) (totalSeconds % 60); + totalSeconds /= 60; + uint32_t hours = (uint32_t) (totalSeconds % 24); + totalSeconds /= 24; + uint32_t days = (uint32_t) totalSeconds; + + if(days > 0) + { + if(options->durationAbbreviation) + { + ffStrbufAppendF(result, "%u%sd", days, space); + + if(hours > 0 || minutes > 0) + ffStrbufAppendC(result, ' '); + } + else + { + ffStrbufAppendF(result, "%u%sday", days, space); + + if(days > 1) + ffStrbufAppendC(result, 's'); + + if(days >= 100) + ffStrbufAppendS(result, "(!)"); + + if(hours > 0 || minutes > 0) + ffStrbufAppendS(result, ", "); + } + } + + if(hours > 0) + { + if(options->durationAbbreviation) + { + ffStrbufAppendF(result, "%u%sh", hours, space); + + if (minutes > 0) + ffStrbufAppendC(result, ' '); + } + else + { + ffStrbufAppendF(result, "%u%shour", hours, space); + + if(hours > 1) + ffStrbufAppendC(result, 's'); + + if(minutes > 0) + ffStrbufAppendS(result, ", "); + } + } + + if(minutes > 0) + { + if(options->durationAbbreviation) + { + ffStrbufAppendF(result, "%u%sm", minutes, space); + } + else + { + ffStrbufAppendF(result, "%u%smin", minutes, space); + + if(minutes > 1) + ffStrbufAppendC(result, 's'); + } + } +} diff --git a/src/common/duration.h b/src/common/duration.h new file mode 100644 index 000000000..234a2c976 --- /dev/null +++ b/src/common/duration.h @@ -0,0 +1,3 @@ +#include "fastfetch.h" + +void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result); diff --git a/src/common/frequency.c b/src/common/frequency.c new file mode 100644 index 000000000..248bb0638 --- /dev/null +++ b/src/common/frequency.c @@ -0,0 +1,17 @@ +#include "frequency.h" + +bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result) +{ + if (mhz == 0) + return false; + + const FFOptionsDisplay* options = &instance.config.display; + const char* space = options->freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " "; + int8_t ndigits = options->freqNdigits; + + if (ndigits >= 0) + ffStrbufAppendF(result, "%.*f%sGHz", ndigits, mhz / 1000., space); + else + ffStrbufAppendF(result, "%u%sMHz", (unsigned) mhz, space); + return true; +} diff --git a/src/common/frequency.h b/src/common/frequency.h new file mode 100644 index 000000000..53dacf803 --- /dev/null +++ b/src/common/frequency.h @@ -0,0 +1,3 @@ +#include "fastfetch.h" + +bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result); diff --git a/src/common/parsing.c b/src/common/parsing.c index 7aeea191e..00de9a8d5 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -2,7 +2,6 @@ #include "common/parsing.h" #include -#include #ifdef _WIN32 #pragma GCC diagnostic push @@ -60,56 +59,6 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty) ffStrbufAppendF(pretty, ".%u", version->patch); } -static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const char** prefixes) -{ - double size = (double) bytes; - uint8_t counter = 0; - - while(size >= base && counter < instance.config.display.sizeMaxPrefix && prefixes[counter + 1]) - { - size /= base; - counter++; - } - - if(counter == 0) - ffStrbufAppendF(result, "%" PRIu64 " %s", bytes, prefixes[0]); - else - ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]); -} - -void ffParseSize(uint64_t bytes, FFstrbuf* result) -{ - switch (instance.config.display.sizeBinaryPrefix) - { - case FF_SIZE_BINARY_PREFIX_TYPE_IEC: - parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL}); - break; - case FF_SIZE_BINARY_PREFIX_TYPE_SI: - parseSize(result, bytes, 1000, (const char*[]) {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL}); - break; - case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC: - parseSize(result, bytes, 1024, (const char*[]) {"B", "KB", "MB", "GB", "TB", NULL}); - break; - default: - parseSize(result, bytes, 1024, (const char*[]) {"B", NULL}); - break; - } -} - -bool ffParseFrequency(uint32_t mhz, FFstrbuf* result) -{ - if (mhz == 0) - return false; - - int8_t ndigits = instance.config.display.freqNdigits; - - if (ndigits >= 0) - ffStrbufAppendF(result, "%.*f GHz", ndigits, mhz / 1000.); - else - ffStrbufAppendF(result, "%u MHz", (unsigned) mhz); - return true; -} - void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4) { if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0) @@ -190,61 +139,6 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co } } -void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result) -{ - if(totalSeconds < 60) - { - ffStrbufAppendF(result, "%u second", (unsigned) totalSeconds); - if (totalSeconds != 1) - ffStrbufAppendC(result, 's'); - return; - } - - uint32_t seconds = (uint32_t) (totalSeconds % 60); - totalSeconds /= 60; - if (seconds >= 30) - totalSeconds++; - - uint32_t minutes = (uint32_t) (totalSeconds % 60); - totalSeconds /= 60; - uint32_t hours = (uint32_t) (totalSeconds % 24); - totalSeconds /= 24; - uint32_t days = (uint32_t) totalSeconds; - - if(days > 0) - { - ffStrbufAppendF(result, "%u day", days); - - if(days > 1) - ffStrbufAppendC(result, 's'); - - if(days >= 100) - ffStrbufAppendS(result, "(!)"); - - if(hours > 0 || minutes > 0) - ffStrbufAppendS(result, ", "); - } - - if(hours > 0) - { - ffStrbufAppendF(result, "%u hour", hours); - - if(hours > 1) - ffStrbufAppendC(result, 's'); - - if(minutes > 0) - ffStrbufAppendS(result, ", "); - } - - if(minutes > 0) - { - ffStrbufAppendF(result, "%u min", minutes); - - if(minutes > 1) - ffStrbufAppendC(result, 's'); - } -} - #ifdef _WIN32 #pragma GCC diagnostic pop #endif diff --git a/src/common/parsing.h b/src/common/parsing.h index af72f441d..f18987906 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -24,7 +24,3 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty); int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2); - -void ffParseSize(uint64_t bytes, FFstrbuf* result); -bool ffParseFrequency(uint32_t mhz, FFstrbuf* result); -void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result); diff --git a/src/common/percent.c b/src/common/percent.c index 8a1dffc14..8e4a0c24d 100644 --- a/src/common/percent.c +++ b/src/common/percent.c @@ -175,7 +175,6 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConf ffStrbufAppendF(buffer, "\e[%sm", colorYellow); else ffStrbufAppendF(buffer, "\e[%sm", colorGreen); - } else { @@ -187,7 +186,8 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConf ffStrbufAppendF(buffer, "\e[%sm", colorGreen); } } - ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent); + ffStrbufAppendF(buffer, "%.*f%s%%", options->percentNdigits, percent, + options->percentSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : ""); if (colored && !options->pipe) { diff --git a/src/common/size.c b/src/common/size.c new file mode 100644 index 000000000..f32b02181 --- /dev/null +++ b/src/common/size.c @@ -0,0 +1,42 @@ +#include "size.h" + +#include + +static void appendNum(FFstrbuf* result, uint64_t bytes, uint32_t base, const char** prefixes) +{ + const FFOptionsDisplay* options = &instance.config.display; + double size = (double) bytes; + uint8_t counter = 0; + + while(size >= base && counter < options->sizeMaxPrefix && prefixes[counter + 1]) + { + size /= base; + counter++; + } + + const char* space = options->sizeSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " "; + if(counter == 0) + ffStrbufAppendF(result, "%" PRIu64 "%s%s", bytes, space, prefixes[0]); + else + ffStrbufAppendF(result, "%.*f%s%s", options->sizeNdigits, size, space, prefixes[counter]); +} + +void ffSizeAppendNum(uint64_t bytes, FFstrbuf* result) +{ + const FFOptionsDisplay* options = &instance.config.display; + switch (options->sizeBinaryPrefix) + { + case FF_SIZE_BINARY_PREFIX_TYPE_IEC: + appendNum(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL}); + break; + case FF_SIZE_BINARY_PREFIX_TYPE_SI: + appendNum(result, bytes, 1000, (const char*[]) {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL}); + break; + case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC: + appendNum(result, bytes, 1024, (const char*[]) {"B", "KB", "MB", "GB", "TB", NULL}); + break; + default: + appendNum(result, bytes, 1024, (const char*[]) {"B", NULL}); + break; + } +} diff --git a/src/common/size.h b/src/common/size.h new file mode 100644 index 000000000..f234d5ae0 --- /dev/null +++ b/src/common/size.h @@ -0,0 +1,3 @@ +#include "fastfetch.h" + +void ffSizeAppendNum(uint64_t bytes, FFstrbuf* result); diff --git a/src/common/temps.c b/src/common/temps.c index 10e11de61..3e1e59c54 100644 --- a/src/common/temps.c +++ b/src/common/temps.c @@ -41,13 +41,16 @@ void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig confi { case FF_TEMPERATURE_UNIT_DEFAULT: case FF_TEMPERATURE_UNIT_CELSIUS: - ffStrbufAppendF(buffer, "%.*f°C", options->tempNdigits, celsius); + ffStrbufAppendF(buffer, "%.*f%s°C", options->tempNdigits, celsius, + options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : ""); break; case FF_TEMPERATURE_UNIT_FAHRENHEIT: - ffStrbufAppendF(buffer, "%.*f°F", options->tempNdigits, celsius * 1.8 + 32); + ffStrbufAppendF(buffer, "%.*f%s°F", options->tempNdigits, celsius * 1.8 + 32, + options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : ""); break; case FF_TEMPERATURE_UNIT_KELVIN: - ffStrbufAppendF(buffer, "%.*f K", options->tempNdigits, celsius + 273.15); + ffStrbufAppendF(buffer, "%.*f%sK", options->tempNdigits, celsius + 273.15, + options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " "); break; } diff --git a/src/data/help.json b/src/data/help.json index 788428a23..552affcca 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -454,7 +454,8 @@ "remark": "Auto-detected based on isatty(1) by default", "arg": { "type": "bool", - "optional": true + "optional": true, + "default": false } }, { @@ -500,6 +501,28 @@ "type": "color" } }, + { + "long": "duration-abbreviation", + "desc": "Specify whether to abbreviate duration values", + "remark": "If true, the output will be in the form of \"1h 2m\" instead of \"1 hour, 2 mins\"", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, + { + "long": "duration-space-before-unit", + "desc": "Specify whether to put a space before the unit in duration values", + "arg": { + "type": "enum", + "enum": { + "default": "Use the default behavior of the module", + "always": "Always put a space before the unit", + "never": "Never put a space before the unit" + } + } + }, { "long": "key-width", "desc": "Align the width of keys to characters", @@ -623,6 +646,18 @@ "default": "light_red" } }, + { + "long": "percent-space-before-unit", + "desc": "Specify whether to put a space before the percentage symbol", + "arg": { + "type": "enum", + "enum": { + "default": "Use the default behavior of the module", + "always": "Always put a space before the unit", + "never": "Never put a space before the unit" + } + } + }, { "long": "bar-char-elapsed", "desc": "Set the character to use in the elapsed part of percentage bars", @@ -711,6 +746,18 @@ "default": "YB" } }, + { + "long": "size-space-before-unit", + "desc": "Specify whether to put a space before the unit", + "arg": { + "type": "enum", + "enum": { + "default": "Use the default behavior of the module", + "always": "Always put a space before the unit", + "never": "Never put a space before the unit" + } + } + }, { "long": "freq-ndigits", "desc": "Set the number of digits to keep after the decimal point when printing CPU/GPU frequency in GHz", @@ -719,6 +766,18 @@ "default": 2 } }, + { + "long": "freq-space-before-unit", + "desc": "Specify whether to put a space before the unit", + "arg": { + "type": "enum", + "enum": { + "default": "Use the default behavior of the module", + "always": "Always put a space before the unit", + "never": "Never put a space before the unit" + } + } + }, { "long": "fraction-ndigits", "desc": "Set the number of digits to keep after the decimal point when printing ordinary fraction numbers", @@ -776,6 +835,18 @@ "type": "color", "default": "light_red" } + }, + { + "long": "temp-space-before-unit", + "desc": "Specify whether to put a space before the unit", + "arg": { + "type": "enum", + "enum": { + "default": "Use the default behavior of the module", + "always": "Always put a space before the unit", + "never": "Never put a space before the unit" + } + } } ], "Module specific": [ diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index ba2327e34..b45995b35 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -1,7 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" #include "common/percent.h" -#include "common/parsing.h" +#include "common/duration.h" #include "common/temps.h" #include "detection/battery/battery.h" #include "modules/battery/battery.h" @@ -59,7 +59,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin if(str.length > 0) ffStrbufAppendS(&str, " ("); - ffParseDuration((uint32_t) result->timeRemaining, &str); + ffDurationAppendNum((uint32_t) result->timeRemaining, &str); ffStrbufAppendS(&str, " remaining)"); } } diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 02ebf6032..31b58e1f3 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -1,6 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" #include "common/percent.h" +#include "common/size.h" #include "detection/btrfs/btrfs.h" #include "modules/btrfs/btrfs.h" #include "util/stringUtils.h" @@ -34,11 +35,11 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i } FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate(); - ffParseSize(used, &usedPretty); + ffSizeAppendNum(used, &usedPretty); FF_STRBUF_AUTO_DESTROY allocatedPretty = ffStrbufCreate(); - ffParseSize(allocated, &allocatedPretty); + ffSizeAppendNum(allocated, &allocatedPretty); FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate(); - ffParseSize(total, &totalPretty); + ffSizeAppendNum(total, &totalPretty); double usedPercentage = total > 0 ? (double) used / (double) total * 100.0 : 0; double allocatedPercentage = total > 0 ? (double) allocated / (double) total * 100.0 : 0; @@ -74,9 +75,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i ffPercentAppendBar(&allocatedPercentageBar, allocatedPercentage, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY nodeSizePretty = ffStrbufCreate(); - ffParseSize(result->nodeSize, &nodeSizePretty); + ffSizeAppendNum(result->nodeSize, &nodeSizePretty); FF_STRBUF_AUTO_DESTROY sectorSizePretty = ffStrbufCreate(); - ffParseSize(result->sectorSize, §orSizePretty); + ffSizeAppendNum(result->sectorSize, §orSizePretty); FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) { FF_FORMAT_ARG(result->name, "name"), diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 178574aa0..2511a6b04 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -2,6 +2,7 @@ #include "common/jsonconfig.h" #include "common/parsing.h" #include "common/temps.h" +#include "common/frequency.h" #include "detection/cpu/cpu.h" #include "modules/cpu/cpu.h" #include "util/stringUtils.h" @@ -77,7 +78,7 @@ void ffPrintCPU(FFCPUOptions* options) if(freq > 0) { ffStrbufAppendS(&str, " @ "); - ffParseFrequency(freq, &str); + ffFreqAppendNum(freq, &str); } if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET @@ -91,9 +92,9 @@ void ffPrintCPU(FFCPUOptions* options) else { FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBase, &freqBase); + ffFreqAppendNum(cpu.frequencyBase, &freqBase); FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyMax, &freqMax); + ffFreqAppendNum(cpu.frequencyMax, &freqMax); FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 2be8f4551..64eaa0612 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -1,5 +1,6 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "common/size.h" #include "detection/cpucache/cpucache.h" #include "modules/cpucache/cpucache.h" #include "util/stringUtils.h" @@ -45,7 +46,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption ffStrbufAppendS(&buffer, ", "); if (src->num > 1) ffStrbufAppendF(&buffer, "%ux", src->num); - ffParseSize(src->size, &buffer); + ffSizeAppendNum(src->size, &buffer); ffStrbufAppendF(&buffer, " (%c)", typeStr); sum += src->size * src->num; @@ -59,7 +60,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption else { FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); - ffParseSize(sum, &buffer2); + ffSizeAppendNum(sum, &buffer2); FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) { FF_FORMAT_ARG(buffer, "result"), FF_FORMAT_ARG(buffer2, "sum"), @@ -79,7 +80,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio uint32_t value = 0; FF_LIST_FOR_EACH(FFCPUCache, src, result->caches[i]) value += src->size * src->num; - ffParseSize(value, &buffer); + ffSizeAppendNum(value, &buffer); ffStrbufAppendF(&buffer, " (L%u)", i + 1); sum += value; } @@ -92,7 +93,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio else { FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); - ffParseSize(sum, &buffer2); + ffSizeAppendNum(sum, &buffer2); FF_PRINT_FORMAT_CHECKED(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_FORMAT_ARG(buffer, "result"), FF_FORMAT_ARG(buffer2, "sum"), diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index b84012443..1596b3861 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -1,7 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" #include "common/percent.h" +#include "common/size.h" #include "common/time.h" #include "detection/disk/disk.h" #include "modules/disk/disk.h" @@ -44,10 +44,10 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index } FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate(); - ffParseSize(disk->bytesUsed, &usedPretty); + ffSizeAppendNum(disk->bytesUsed, &usedPretty); FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate(); - ffParseSize(disk->bytesTotal, &totalPretty); + ffSizeAppendNum(disk->bytesTotal, &totalPretty); double bytesPercentage = disk->bytesTotal > 0 ? (double) disk->bytesUsed / (double) disk->bytesTotal * 100.0 : 0; FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index b73237783..19af8eb3c 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -1,6 +1,6 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" +#include "common/size.h" #include "detection/diskio/diskio.h" #include "modules/diskio/diskio.h" #include "util/stringUtils.h" @@ -57,21 +57,21 @@ void ffPrintDiskIO(FFDiskIOOptions* options) { ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); - ffParseSize(dev->bytesRead, &buffer); + ffSizeAppendNum(dev->bytesRead, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); ffStrbufAppendS(&buffer, " (R) - "); - ffParseSize(dev->bytesWritten, &buffer); + ffSizeAppendNum(dev->bytesWritten, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); ffStrbufAppendS(&buffer, " (W)"); ffStrbufPutTo(&buffer, stdout); } else { - ffParseSize(dev->bytesRead, &buffer); + ffSizeAppendNum(dev->bytesRead, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); ffStrbufClear(&buffer2); - ffParseSize(dev->bytesWritten, &buffer2); + ffSizeAppendNum(dev->bytesWritten, &buffer2); if (!options->detectTotal) ffStrbufAppendS(&buffer2, "/s"); FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){ diff --git a/src/modules/display/display.c b/src/modules/display/display.c index a55c15d83..437bc79f6 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -1,5 +1,6 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "common/size.h" #include "detection/displayserver/displayserver.h" #include "modules/display/display.h" #include "util/stringUtils.h" @@ -51,10 +52,11 @@ void ffPrintDisplay(FFDisplayOptions* options) { if (result->refreshRate > 0) { + const char* space = instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : ""; if (options->preciseRefreshRate) - ffStrbufAppendF(&buffer, " @ %gHz", result->refreshRate); + ffStrbufAppendF(&buffer, " @ %g%sHz", result->refreshRate, space); else - ffStrbufAppendF(&buffer, " @ %iHz", (uint32_t) (result->refreshRate + 0.5)); + ffStrbufAppendF(&buffer, " @ %i%sHz", (uint32_t) (result->refreshRate + 0.5), space); } ffStrbufAppendS(&buffer, ", "); } @@ -108,10 +110,11 @@ void ffPrintDisplay(FFDisplayOptions* options) if(result->refreshRate > 0) { + const char* space = instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " "; if(options->preciseRefreshRate) - ffStrbufAppendF(&buffer, " @ %g Hz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); + ffStrbufAppendF(&buffer, " @ %g%sHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0, space); else - ffStrbufAppendF(&buffer, " @ %i Hz", (uint32_t) (result->refreshRate + 0.5)); + ffStrbufAppendF(&buffer, " @ %i%sHz", (uint32_t) (result->refreshRate + 0.5), space); } if( diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 7d917c83d..f2f5806c7 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -1,8 +1,9 @@ #include "common/percent.h" -#include "common/parsing.h" #include "common/printing.h" #include "common/jsonconfig.h" #include "common/temps.h" +#include "common/size.h" +#include "common/frequency.h" #include "detection/host/host.h" #include "detection/gpu/gpu.h" #include "modules/gpu/gpu.h" @@ -42,7 +43,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu if(gpu->frequency > 0) { ffStrbufAppendS(&output, " @ "); - ffParseFrequency(gpu->frequency, &output); + ffFreqAppendNum(gpu->frequency, &output); } if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET @@ -59,10 +60,10 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu { if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { - ffParseSize(gpu->dedicated.used, &output); + ffSizeAppendNum(gpu->dedicated.used, &output); ffStrbufAppendS(&output, " / "); } - ffParseSize(gpu->dedicated.total, &output); + ffSizeAppendNum(gpu->dedicated.total, &output); } if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { @@ -94,8 +95,8 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FF_STRBUF_AUTO_DESTROY dUsed = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY dPercentNum = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY dPercentBar = ffStrbufCreate(); - if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->dedicated.total, &dTotal); - if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->dedicated.used, &dUsed); + if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->dedicated.total, &dTotal); + if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->dedicated.used, &dUsed); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { double percent = (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0; @@ -109,8 +110,8 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FF_STRBUF_AUTO_DESTROY sUsed = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY sPercentNum = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY sPercentBar = ffStrbufCreate(); - if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->shared.total, &sTotal); - if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->shared.used, &sUsed); + if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->shared.total, &sTotal); + if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->shared.used, &sUsed); if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET && gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) { double percent = (double) gpu->shared.used / (double) gpu->shared.total * 100.0; @@ -121,7 +122,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu } FF_STRBUF_AUTO_DESTROY frequency = ffStrbufCreate(); - ffParseFrequency(gpu->frequency, &frequency); + ffFreqAppendNum(gpu->frequency, &frequency); FF_STRBUF_AUTO_DESTROY coreUsageNum = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY coreUsageBar = ffStrbufCreate(); diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 44c85668b..d747e6752 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -1,5 +1,6 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "common/size.h" #include "modules/kernel/kernel.h" #include "util/stringUtils.h" @@ -19,7 +20,7 @@ void ffPrintKernel(FFKernelOptions* options) else { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - ffParseSize(info->pageSize, &str); + ffSizeAppendNum(info->pageSize, &str); FF_PRINT_FORMAT_CHECKED(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_FORMAT_ARG(info->name, "sysname"), FF_FORMAT_ARG(info->release, "release"), diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 0af03736d..deac7ef91 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -1,7 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" #include "common/percent.h" +#include "common/size.h" #include "detection/memory/memory.h" #include "modules/memory/memory.h" #include "util/stringUtils.h" @@ -18,10 +18,10 @@ void ffPrintMemory(FFMemoryOptions* options) } FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate(); - ffParseSize(storage.bytesUsed, &usedPretty); + ffSizeAppendNum(storage.bytesUsed, &usedPretty); FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate(); - ffParseSize(storage.bytesTotal, &totalPretty); + ffSizeAppendNum(storage.bytesTotal, &totalPretty); double percentage = storage.bytesTotal == 0 ? 0 diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index d49ca61f9..5b0fb4bbb 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -1,6 +1,6 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" +#include "common/size.h" #include "detection/netio/netio.h" #include "modules/netio/netio.h" #include "util/stringUtils.h" @@ -59,11 +59,11 @@ void ffPrintNetIO(FFNetIOOptions* options) { ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); - ffParseSize(inf->rxBytes, &buffer); + ffSizeAppendNum(inf->rxBytes, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); ffStrbufAppendS(&buffer, " (IN) - "); - ffParseSize(inf->txBytes, &buffer); + ffSizeAppendNum(inf->txBytes, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); ffStrbufAppendS(&buffer, " (OUT)"); @@ -74,9 +74,9 @@ void ffPrintNetIO(FFNetIOOptions* options) else { ffStrbufClear(&buffer2); - ffParseSize(inf->rxBytes, &buffer); + ffSizeAppendNum(inf->rxBytes, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); - ffParseSize(inf->txBytes, &buffer2); + ffSizeAppendNum(inf->txBytes, &buffer2); if (!options->detectTotal) ffStrbufAppendS(&buffer2, "/s"); FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){ diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index de6751791..f68770697 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -1,7 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" #include "common/temps.h" +#include "common/size.h" #include "detection/physicaldisk/physicaldisk.h" #include "modules/physicaldisk/physicaldisk.h" #include "util/stringUtils.h" @@ -52,7 +52,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) { formatKey(options, dev, result.length == 1 ? 0 : index + 1, &key); ffStrbufClear(&buffer); - ffParseSize(dev->size, &buffer); + ffSizeAppendNum(dev->size, &buffer); const char* physicalType = dev->type & FF_PHYSICALDISK_TYPE_HDD ? "HDD" diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 5ea3573a9..4bfe28ef4 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -1,7 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" #include "common/percent.h" +#include "common/size.h" #include "detection/physicalmemory/physicalmemory.h" #include "modules/physicalmemory/physicalmemory.h" #include "util/stringUtils.h" @@ -32,7 +32,7 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { ++i; ffStrbufClear(&prettySize); - ffParseSize(device->size, &prettySize); + ffSizeAppendNum(device->size, &prettySize); if (options->moduleArgs.outputFormat.length == 0) { diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index c4a28f67b..fb3072f44 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -1,7 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/parsing.h" #include "common/percent.h" +#include "common/size.h" #include "detection/swap/swap.h" #include "modules/swap/swap.h" #include "util/stringUtils.h" @@ -28,10 +28,10 @@ void printSwap(FFSwapOptions* options, uint8_t index, FFSwapResult* storage) } FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate(); - ffParseSize(storage->bytesUsed, &usedPretty); + ffSizeAppendNum(storage->bytesUsed, &usedPretty); FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate(); - ffParseSize(storage->bytesTotal, &totalPretty); + ffSizeAppendNum(storage->bytesTotal, &totalPretty); double percentage = storage->bytesTotal == 0 ? 0 diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 445de7e1f..c0118686a 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -1,3 +1,4 @@ +#include "common/duration.h" #include "common/printing.h" #include "common/jsonconfig.h" #include "common/time.h" @@ -23,7 +24,7 @@ void ffPrintUptime(FFUptimeOptions* options) { ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - ffParseDuration((uptime + 500) / 1000, &buffer); + ffDurationAppendNum((uptime + 500) / 1000, &buffer); ffStrbufPutTo(&buffer, stdout); } diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index cae5150dd..c7038a0fc 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -74,7 +74,10 @@ void ffPrintWifi(FFWifiOptions* options) ffStrbufAppend(&buffer, &item->conn.protocol); } if (bandStr[0]) - ffStrbufAppendF(&buffer, " - %s GHz", bandStr); + { + ffStrbufAppendF(&buffer, " - %s%sGHz", bandStr, + instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " "); + } if(item->conn.security.length) { ffStrbufAppendS(&buffer, " - "); diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index a00274e70..151836f0b 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -1,6 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" #include "common/percent.h" +#include "common/size.h" #include "detection/zpool/zpool.h" #include "modules/zpool/zpool.h" #include "util/stringUtils.h" @@ -26,10 +27,10 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i } FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate(); - ffParseSize(result->used, &usedPretty); + ffSizeAppendNum(result->used, &usedPretty); FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate(); - ffParseSize(result->total, &totalPretty); + ffSizeAppendNum(result->total, &totalPretty); double bytesPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0; FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; diff --git a/src/options/display.c b/src/options/display.c index cc4b703e6..5eb1e33e5 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -78,6 +78,28 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va options->brightColor = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "binaryPrefix")) return "`display.binaryPrefix` has been renamed to `display.size.binaryPrefix`. Sorry for another break change."; + else if (ffStrEqualsIgnCase(key, "duration")) + { + if (!yyjson_is_obj(val)) + return "display.duration must be an object"; + + yyjson_val* abbreviation = yyjson_obj_get(val, "abbreviation"); + if (abbreviation) options->durationAbbreviation = yyjson_get_bool(abbreviation); + + yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit"); + if (spaceBeforeUnit) + { + int value; + const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + if (error) return error; + options->durationSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; + } + } else if (ffStrEqualsIgnCase(key, "size")) { if (!yyjson_is_obj(val)) @@ -119,6 +141,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); if (ndigits) options->sizeNdigits = (uint8_t) yyjson_get_uint(ndigits); + + yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit"); + if (spaceBeforeUnit) + { + int value; + const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + if (error) return error; + options->sizeSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; + } } else if (ffStrEqualsIgnCase(key, "temp")) { @@ -162,6 +198,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val* red = yyjson_obj_get(color, "red"); if (red) ffOptionParseColor(yyjson_get_str(red), &options->tempColorRed); } + + yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit"); + if (spaceBeforeUnit) + { + int value; + const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + if (error) return error; + options->tempSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; + } } else if (ffStrEqualsIgnCase(key, "percent")) { @@ -193,6 +243,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val* red = yyjson_obj_get(color, "red"); if (red) ffOptionParseColor(yyjson_get_str(red), &options->percentColorRed); } + + yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit"); + if (spaceBeforeUnit) + { + int value; + const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + if (error) return error; + options->percentSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; + } } else if (ffStrEqualsIgnCase(key, "bar")) { @@ -288,6 +352,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); if (ndigits) options->freqNdigits = (int8_t) yyjson_get_int(ndigits); + + yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit"); + if (spaceBeforeUnit) + { + int value; + const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + if (error) return error; + options->freqSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; + } } else return "Unknown display property"; @@ -403,6 +481,23 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key fprintf(stderr, "--binary-prefix has been renamed to --size-binary-prefix\n"); exit(477); } + else if(ffStrStartsWithIgnCase(key, "--duration-")) + { + const char* subkey = key + strlen("--duration-"); + if(ffStrEqualsIgnCase(subkey, "abbreviation")) + options->durationAbbreviation = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(subkey, "space-before-unit")) + { + options->durationSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + } + else + return false; + } else if(ffStrStartsWithIgnCase(key, "--size-")) { const char* subkey = key + strlen("--size-"); @@ -432,6 +527,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key {} }); } + else if(ffStrEqualsIgnCase(subkey, "space-before-unit")) + { + options->sizeSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + } else return false; } @@ -460,6 +564,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key ffOptionParseColor(value, &options->tempColorYellow); else if(ffStrEqualsIgnCase(subkey, "color-red")) ffOptionParseColor(value, &options->tempColorRed); + else if(ffStrEqualsIgnCase(subkey, "space-before-unit")) + { + options->tempSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + } else return false; } @@ -476,6 +589,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key ffOptionParseColor(value, &options->percentColorYellow); else if(ffStrEqualsIgnCase(subkey, "color-red")) ffOptionParseColor(value, &options->percentColorRed); + else if(ffStrEqualsIgnCase(subkey, "space-before-unit")) + { + options->percentSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + } else return false; } @@ -504,6 +626,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key const char* subkey = key + strlen("--freq-"); if(ffStrEqualsIgnCase(subkey, "ndigits")) options->freqNdigits = (int8_t) ffOptionParseInt32(key, value); + else if(ffStrEqualsIgnCase(subkey, "space-before-unit")) + { + options->freqSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, + { "always", FF_SPACE_BEFORE_UNIT_ALWAYS }, + { "never", FF_SPACE_BEFORE_UNIT_NEVER }, + {}, + }); + } else return false; } @@ -531,10 +662,13 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) options->debugMode = false; #endif + options->durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; options->hideCursor = false; options->sizeBinaryPrefix = FF_SIZE_BINARY_PREFIX_TYPE_IEC; options->sizeNdigits = 2; options->sizeMaxPrefix = UINT8_MAX; + options->sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; + options->stat = -1; options->noBuffer = false; options->keyWidth = 0; @@ -546,18 +680,24 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->tempColorGreen, FF_COLOR_FG_GREEN); ffStrbufInitStatic(&options->tempColorYellow, instance.state.terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW); ffStrbufInitStatic(&options->tempColorRed, instance.state.terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED); + options->tempSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; ffStrbufInitStatic(&options->barCharElapsed, "■"); ffStrbufInitStatic(&options->barCharTotal, "-"); ffStrbufInitStatic(&options->barBorderLeft, "[ "); ffStrbufInitStatic(&options->barBorderRight, " ]"); options->barWidth = 10; + options->durationAbbreviation = false; + options->durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; options->percentType = 9; options->percentNdigits = 0; ffStrbufInitStatic(&options->percentColorGreen, FF_COLOR_FG_GREEN); ffStrbufInitStatic(&options->percentColorYellow, instance.state.terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW); ffStrbufInitStatic(&options->percentColorRed, instance.state.terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED); + options->percentSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; + options->freqNdigits = 2; + options->freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; options->fractionNdigits = -1; ffListInit(&options->constants, sizeof(FFstrbuf)); diff --git a/src/options/display.h b/src/options/display.h index d531dd7bc..cc516e877 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -17,6 +17,13 @@ typedef enum __attribute__((__packed__)) FFTemperatureUnit FF_TEMPERATURE_UNIT_KELVIN, } FFTemperatureUnit; +typedef enum __attribute__((__packed__)) FFSpaceBeforeUnitType +{ + FF_SPACE_BEFORE_UNIT_DEFAULT, + FF_SPACE_BEFORE_UNIT_ALWAYS, + FF_SPACE_BEFORE_UNIT_NEVER, +} FFSpaceBeforeUnitType; + typedef struct FFOptionsDisplay { //If one of those is empty, ffLogoPrint will set them @@ -36,15 +43,19 @@ typedef struct FFOptionsDisplay bool debugMode; #endif bool disableLinewrap; + bool durationAbbreviation; + FFSpaceBeforeUnitType durationSpaceBeforeUnit; bool hideCursor; FFSizeBinaryPrefixType sizeBinaryPrefix; uint8_t sizeNdigits; uint8_t sizeMaxPrefix; + FFSpaceBeforeUnitType sizeSpaceBeforeUnit; FFTemperatureUnit tempUnit; uint8_t tempNdigits; FFstrbuf tempColorGreen; FFstrbuf tempColorYellow; FFstrbuf tempColorRed; + FFSpaceBeforeUnitType tempSpaceBeforeUnit; FFstrbuf barCharElapsed; FFstrbuf barCharTotal; FFstrbuf barBorderLeft; @@ -55,12 +66,15 @@ typedef struct FFOptionsDisplay FFstrbuf percentColorGreen; FFstrbuf percentColorYellow; FFstrbuf percentColorRed; + FFSpaceBeforeUnitType percentSpaceBeforeUnit; bool noBuffer; FFModuleKeyType keyType; uint16_t keyWidth; uint16_t keyPaddingLeft; int8_t freqNdigits; + FFSpaceBeforeUnitType freqSpaceBeforeUnit; int8_t fractionNdigits; + FFlist constants; // list of FFstrbuf } FFOptionsDisplay; diff --git a/tests/duration.c b/tests/duration.c index 0e5c9fb07..283b31801 100644 --- a/tests/duration.c +++ b/tests/duration.c @@ -1,4 +1,4 @@ -#include "common/parsing.h" +#include "common/duration.h" #include "util/textModifier.h" #include "fastfetch.h" @@ -7,7 +7,7 @@ static void verify(uint64_t totalSeconds, const char* expected, int lineNo) { FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); - ffParseDuration(totalSeconds, &result); + ffDurationAppendNum(totalSeconds, &result); if (!ffStrbufEqualS(&result, expected)) { fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %llu: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, (unsigned long long) totalSeconds, expected, result.chars); @@ -66,6 +66,55 @@ int main(void) VERIFY(60 * 60 * 24 * 100, "100 days(!)"); VERIFY(60 * 60 * 24 * 200, "200 days(!)"); + instance.config.display.durationAbbreviation = true; + instance.config.display.durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER; + // Test seconds less than 60 + VERIFY(0, "0secs"); + VERIFY(1, "1sec"); + VERIFY(2, "2secs"); + VERIFY(59, "59secs"); + + // Test minute rounding (when seconds >= 30) + VERIFY(60, "1m"); + VERIFY(60 + 29, "1m"); + VERIFY(60 + 30, "2m"); + + // Test only minutes + VERIFY(60 * 2 - 1, "2m"); + VERIFY(60 * 2, "2m"); + VERIFY(60 * 59 + 29, "59m"); + + // Test only hours (no minutes) + VERIFY(60 * 59 + 30, "1h"); + VERIFY(60 * 60, "1h"); + VERIFY(2 * 60 * 60, "2h"); + VERIFY(23 * 60 * 60, "23h"); + + // Test combination of hours and minutes + VERIFY(60 * 60 + 60, "1h 1m"); + VERIFY(60 * 60 + 60 * 2, "1h 2m"); + VERIFY(60 * 60 * 2 + 60 + 29, "2h 1m"); + VERIFY(60 * 60 * 2 + 60 + 30, "2h 2m"); + + // Test days + VERIFY(60 * 60 * 24, "1d"); + VERIFY(60 * 60 * 24 - 1, "1d"); + VERIFY(60 * 60 * 24 * 2, "2d"); + + // Test combination of days and hours + VERIFY(60 * 60 * 24 + 60 * 60, "1d 1h"); + VERIFY(60 * 60 * 24 * 2 + 60 * 60, "2d 1h"); + VERIFY(60 * 60 * 24 * 2 + 60 * 60 * 2, "2d 2h"); + + // Test combination of days, hours, and minutes + VERIFY(60 * 60 * 24 + 60 * 60 + 60, "1d 1h 1m"); + VERIFY(60 * 60 * 24 * 2 + 60 * 60 + 60 * 2, "2d 1h 2m"); + VERIFY(60 * 60 * 24 * 2 + 60 * 2, "2d 2m"); + + // Test very large number of days + VERIFY(60 * 60 * 24 * 100, "100d"); + VERIFY(60 * 60 * 24 * 200, "200d"); + //Success puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); }