From f4ee8667b197d6117288b13e7df2964d557542fc Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 26 Aug 2022 16:02:04 +0200 Subject: [PATCH] Binary prefix option --- completions/bash | 1 + src/common/init.c | 1 + src/common/parsing.c | 32 ++++++++++ src/common/parsing.h | 2 + src/data/config_user.txt | 6 ++ src/data/help.txt | 1 + src/fastfetch.c | 123 +++++++++++++++++++++------------------ src/fastfetch.h | 8 +++ src/modules/disk.c | 42 ++++++------- src/modules/memory.c | 43 +++++--------- 10 files changed, 151 insertions(+), 108 deletions(-) diff --git a/completions/bash b/completions/bash index c5aa99ee9..d2a322dea 100644 --- a/completions/bash +++ b/completions/bash @@ -158,6 +158,7 @@ __fastfetch_completion() "--set" "--set-keyless" "--gl" + "--binary-prefix" "--os-format" "--os-key" "--host-format" diff --git a/src/common/init.c b/src/common/init.c index b1f086fb8..e96217806 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -146,6 +146,7 @@ static void defaultConfig(FFinstance* instance) instance->config.disableLinewrap = true; instance->config.hideCursor = true; instance->config.escapeBedrock = true; + instance->config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC; instance->config.glType = FF_GL_TYPE_AUTO; instance->config.pipe = false; instance->config.multithreading = true; diff --git a/src/common/parsing.c b/src/common/parsing.c index f0c434fac..e76029f65 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -1,5 +1,6 @@ #include "fastfetch.h" #include "common/parsing.h" +#include bool ffStrSet(const char* str) { @@ -66,6 +67,37 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty) ffStrbufAppendF(pretty, ".%u", version->patch); } +static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, uint8_t prefixesLength, const char** prefixes) +{ + long double size = (long double) bytes; + uint8_t counter = 0; + + while(size > base && counter < prefixesLength - 1) + { + size /= base; + counter++; + } + + if(counter == 0) + ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]); + else if(counter < 3 || (counter == 3 && size < 100.0)) + ffStrbufAppendF(result, "%.2Lf %s", size, prefixes[counter]); + else + ffStrbufAppendF(result, "%.0Lf %s", size, prefixes[counter]); +} + +void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result) +{ + if(binaryPrefix == FF_BINARY_PREFIX_TYPE_IEC) + parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB"}); + else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_SI) + parseSize(result, bytes, 1000, 5, (const char*[]) {"B", "kB", "MB", "GB", "TB"}); + else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_JEDEC) + parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KB", "MB", "GB", "TB"}); + else + parseSize(result, bytes, 1024, 1, (const char*[]) {"B"}); +} + void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4) { if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0) diff --git a/src/common/parsing.h b/src/common/parsing.h index 28dbfec98..239caa42f 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -21,4 +21,6 @@ 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, FFBinaryPrefixType binaryPrefix, FFstrbuf* result); + #endif diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 2e49183ce..5ef991765 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -120,6 +120,12 @@ # Use "fastfetch --help color" to learn more and see examples. #--color magenta +# Binary prefix option: +# Sets the binary prefix to use. +# Must be a IEC, SI or JEDEC. +# Default is IEC. +#--binary-prefix IEC + # Title FQDN option: # Sets if the title should use the fully qualified domain name. # Must be true or false. diff --git a/src/data/help.txt b/src/data/help.txt index dfa64861b..471c4d705 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -47,6 +47,7 @@ Display options: --show-errors : print occuring errors --disable-linewrap : weather to disable linewrap during the run --hide-cursor : weather to hide the cursor during the run + --binary-prefix : sets the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC General module options: ---format : Sets the format string to use for each specific module. diff --git a/src/fastfetch.c b/src/fastfetch.c index 88858a1f3..89dd5aeec 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -284,23 +284,19 @@ static inline void printCommandHelp(const char* command) } else if(strcasecmp(command, "memory-format") == 0) { - constructAndPrintCommandHelpFormat("memory", "{6}GiB / {7}GiB ({1}%)", 7, - "Percentage", - "Used KiB", - "Total KiB", - "Used MiB", - "Total MiB", - "Used GiB", - "Total GiB" + constructAndPrintCommandHelpFormat("memory", "{} / {} ({}%)", 3, + "Used size", + "Total size", + "Percentage used" ); } else if(strcasecmp(command, "disk-format") == 0) { constructAndPrintCommandHelpFormat("disk", "{}GiB / {}GiB ({4}%)", 4, - "Used disk space", - "Total disk space", - "Number of files", - "Used disk space percentage" + "Used size", + "Total size", + "Percentage used", + "Num files" ); } else if(strcasecmp(command, "battery-format") == 0) @@ -715,6 +711,39 @@ static void optionParseCustomValue(FFdata* data, const char* key, const char* va customValue->printKey = printKey; } +static void optionParseEnum(const char* argumentKey, const char* requestedKey, void* result, ...) +{ + if(requestedKey == NULL) + { + fprintf(stderr, "Error: usage: %s \n", argumentKey); + exit(476); + } + + va_list args; + va_start(args, result); + + while(true) + { + const char* key = va_arg(args, const char*); + if(key == NULL) + break; + + int value = va_arg(args, int); //C standard guarantees that enumeration constants are presented as ints + + if(strcasecmp(requestedKey, key) == 0) + { + *(int*)result = value; + va_end(args); + return; + } + } + + va_end(args); + + fprintf(stderr, "Error: unknown %s value: %s\n", argumentKey, requestedKey); + exit(478); +} + static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value) { /////////////////////// @@ -827,31 +856,16 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con } else if(strcasecmp(key, "--logo-type") == 0) { - if(value == NULL) - { - fprintf(stderr, "Error: usage: %s \n", key); - exit(476); - } - - if(strcasecmp(value, "auto") == 0) - instance->config.logo.type = FF_LOGO_TYPE_AUTO; - else if(strcasecmp(value, "builtin") == 0) - instance->config.logo.type = FF_LOGO_TYPE_BUILTIN; - else if(strcasecmp(value, "file") == 0) - instance->config.logo.type = FF_LOGO_TYPE_FILE; - else if(strcasecmp(value, "raw") == 0) - instance->config.logo.type = FF_LOGO_TYPE_RAW; - else if(strcasecmp(value, "sixel") == 0) - instance->config.logo.type = FF_LOGO_TYPE_SIXEL; - else if(strcasecmp(value, "kitty") == 0) - instance->config.logo.type = FF_LOGO_TYPE_KITTY; - else if(strcasecmp(value, "chafa") == 0) - instance->config.logo.type = FF_LOGO_TYPE_CHAFA; - else - { - fprintf(stderr, "Error: unknown logo type: %s\n", value); - exit(478); - } + optionParseEnum(key, value, &instance->config.logo.type, + "auto", FF_LOGO_TYPE_AUTO, + "builtin", FF_LOGO_TYPE_BUILTIN, + "file", FF_LOGO_TYPE_FILE, + "raw", FF_LOGO_TYPE_RAW, + "sixel", FF_LOGO_TYPE_SIXEL, + "kitty", FF_LOGO_TYPE_KITTY, + "chafa", FF_LOGO_TYPE_CHAFA, + NULL + ); } else if(strncasecmp(key, "--logo-color-", 13) == 0 && key[13] != '\0' && key[14] == '\0') // matches "--logo-color-*" { @@ -929,6 +943,15 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseCustomValue(data, key, value, true); else if(strcasecmp(key, "--set-keyless") == 0) optionParseCustomValue(data, key, value, false); + else if(strcasecmp(key, "--binary-prefix") == 0) + { + optionParseEnum(key, value, &instance->config.binaryPrefixType, + "iec", FF_BINARY_PREFIX_TYPE_IEC, + "si", FF_BINARY_PREFIX_TYPE_SI, + "jedec", FF_BINARY_PREFIX_TYPE_JEDEC, + NULL + ); + } //////////////////////////////// //Format + Key + Error options// @@ -1210,25 +1233,13 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.publicIpTimeout = optionParseUInt32(key, value); else if(strcasecmp(key, "--gl") == 0) { - if(value == NULL) - { - fprintf(stderr, "Error: usage: %s \n", key); - exit(491); - } - - if(strcasecmp(value, "auto") == 0) - instance->config.glType = FF_GL_TYPE_AUTO; - else if(strcasecmp(value, "egl") == 0) - instance->config.glType = FF_GL_TYPE_EGL; - else if(strcasecmp(value, "glx") == 0) - instance->config.glType = FF_GL_TYPE_GLX; - else if(strcasecmp(value, "osmesa") == 0) - instance->config.glType = FF_GL_TYPE_OSMESA; - else - { - fprintf(stderr, "Error: unknown gl type: %s\n", value); - exit(492); - } + optionParseEnum(key, value, &instance->config.glType, + "auto", FF_GL_TYPE_AUTO, + "egl", FF_GL_TYPE_EGL, + "glx", FF_GL_TYPE_GLX, + "osmesa", FF_GL_TYPE_OSMESA, + NULL + ); } ////////////////// diff --git a/src/fastfetch.h b/src/fastfetch.h index 6fd8db956..6d257b0e1 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -35,6 +35,13 @@ typedef enum FFLogoType FF_LOGO_TYPE_CHAFA //Image file, printed as ascii art using libchafa } FFLogoType; +typedef enum FFBinaryPrefixType +{ + FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) + FF_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ... + FF_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 K = 1 MB, ... +} FFBinaryPrefixType; + typedef enum FFGLType { FF_GL_TYPE_AUTO, @@ -74,6 +81,7 @@ typedef struct FFconfig bool disableLinewrap; bool hideCursor; bool escapeBedrock; + FFBinaryPrefixType binaryPrefixType; FFGLType glType; bool pipe; //disables logo and all escape sequences bool multithreading; diff --git a/src/modules/disk.c b/src/modules/disk.c index 1794b63e3..d540f6bd7 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -1,5 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" +#include "common/parsing.h" #include @@ -25,40 +26,31 @@ static void getKey(FFinstance* instance, FFstrbuf* key, const char* folderPath, static void printStatvfs(FFinstance* instance, FFstrbuf* key, struct statvfs* fs) { - const double GB = 1024 * 1024 * 1024; - - double total = ((double) (fs->f_blocks * fs->f_frsize)) / GB; - double available = ((double) (fs->f_bfree * fs->f_frsize)) / GB; - double used = total - available; - uint8_t percentage = (uint8_t) ((used / total) * 100.0); - + uint64_t total = fs->f_blocks * fs->f_frsize; + uint64_t used = total - (fs->f_bfree * fs->f_frsize); uint32_t files = (uint32_t) (fs->f_files - fs->f_ffree); + uint8_t percentage = (uint8_t) ((used / (long double) total) * 100.0); + + FFstrbuf usedPretty; + ffStrbufInit(&usedPretty); + ffParseSize(used, instance->config.binaryPrefixType, &usedPretty); + + FFstrbuf totalPretty; + ffStrbufInit(&totalPretty); + ffParseSize(total, instance->config.binaryPrefixType, &totalPretty); if(instance->config.disk.outputFormat.length == 0) { ffPrintLogoAndKey(instance, key->chars, 0, NULL); - - if(used >= 100.0) - printf("%.0f", used); - else - printf("%.1f", used); - - fputs(" GiB / ", stdout); - - if(total >= 100.0) - printf("%.0f", total); - else - printf("%.1f", total); - - printf("GiB (%u%%)\n", percentage); + printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, percentage); } else { ffPrintFormatString(instance, key->chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_DOUBLE, &used}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &total}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &files}, - {FF_FORMAT_ARG_TYPE_UINT8, &percentage} + {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, + {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, + {FF_FORMAT_ARG_TYPE_UINT8, &percentage}, + {FF_FORMAT_ARG_TYPE_UINT, &files}, }); } } diff --git a/src/modules/memory.c b/src/modules/memory.c index a3c063f63..0da2529a7 100644 --- a/src/modules/memory.c +++ b/src/modules/memory.c @@ -1,20 +1,11 @@ #include "fastfetch.h" #include "common/printing.h" +#include "common/parsing.h" #include #define FF_MEMORY_MODULE_NAME "Memory" -#define FF_MEMORY_NUM_FORMAT_ARGS 7 - -static void printValue(uint32_t kib, double mib, double gib) -{ - if(gib >= 1.0) - printf("%.2f GiB", gib); - else if(mib >= 1.0) - printf("%.2f MiB", mib); - else - printf("%u KiB", kib); -} +#define FF_MEMORY_NUM_FORMAT_ARGS 3 // Impl inspired by: https://github.com/sam-barr/paleofetch/blob/b7c58a52c0de39b53c9b5f417889a5886d324bfa/paleofetch.c#L544 void ffPrintMemory(FFinstance* instance) @@ -52,36 +43,34 @@ void ffPrintMemory(FFinstance* instance) uint32_t used = total + shared - memfree - buffers - cached - reclaimable; uint8_t percentage = (uint8_t) ((used / (double) total) * 100); - double usedMiB = used / 1024.0; - double totalMiB = total / 1024.0; - - double usedGiB = usedMiB / 1024.0; - double totalGiB = totalMiB / 1024.0; - if(used == 0 && total == 0) { ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "/proc/meminfo could't be parsed"); return; } + FFstrbuf usedPretty; + ffStrbufInit(&usedPretty); + ffParseSize(used * (uint64_t) 1024, instance->config.binaryPrefixType, &usedPretty); + + FFstrbuf totalPretty; + ffStrbufInit(&totalPretty); + ffParseSize(total * (uint64_t) 1024, instance->config.binaryPrefixType, &totalPretty); + if(instance->config.memory.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory.key); - printValue(used, usedMiB, usedGiB); - fputs(" / ", stdout); - printValue(total, totalMiB, totalGiB); - printf(" (%u%%)\n", percentage); + printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, percentage); } else { ffPrintFormat(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, + {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, {FF_FORMAT_ARG_TYPE_UINT8, &percentage}, - {FF_FORMAT_ARG_TYPE_UINT, &total}, - {FF_FORMAT_ARG_TYPE_UINT, &used}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &usedMiB}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &totalMiB}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &usedGiB}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &totalGiB} }); } + + ffStrbufDestroy(&usedPretty); + ffStrbufDestroy(&totalPretty); }