From 1ceb5c91acba4c85ca979a145b1f0a68f19f5b06 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 19 Mar 2021 20:57:07 +0100 Subject: [PATCH] format options for every output! --- CMakeLists.txt | 3 +- README.md | 2 +- completions/bash | 53 ++- src/common.c | 224 +++++++++--- src/fastfetch.c | 564 ++++++++++++++++--------------- src/fastfetch.h | 88 ++--- src/flashfetch.c | 6 +- src/logo.c | 2 +- src/modules/battery.c | 116 +++---- src/modules/cpu.c | 24 +- src/modules/de.c | 92 +++++ src/modules/desktopenvironment.c | 45 --- src/modules/disk.c | 32 +- src/modules/font.c | 33 +- src/modules/gpu.c | 32 +- src/modules/host.c | 39 ++- src/modules/icons.c | 38 ++- src/modules/kernel.c | 27 +- src/modules/locale.c | 26 +- src/modules/memory.c | 21 +- src/modules/os.c | 25 +- src/modules/packages.c | 67 ++-- src/modules/resolution.c | 42 ++- src/modules/shell.c | 36 +- src/modules/terminal.c | 34 +- src/modules/terminalfont.c | 50 +-- src/modules/theme.c | 34 +- src/modules/title.c | 2 +- src/modules/uptime.c | 52 ++- src/modules/wm.c | 47 ++- src/util/FFstrbuf.c | 271 +++++++++++++++ src/util/FFstrbuf.h | 64 ++++ src/util/FFvaluestore.h | 2 + tests/performance.c | 2 +- 34 files changed, 1500 insertions(+), 695 deletions(-) create mode 100644 src/modules/de.c delete mode 100644 src/modules/desktopenvironment.c create mode 100644 src/util/FFstrbuf.c create mode 100644 src/util/FFstrbuf.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 28ae425e8..752270fae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ include_directories( set(SRCS src/common.c src/logo.c + src/util/FFstrbuf.c src/modules/break.c src/modules/custom.c src/modules/title.c @@ -44,7 +45,7 @@ set(SRCS src/modules/packages.c src/modules/shell.c src/modules/resolution.c - src/modules/desktopenvironment.c + src/modules/de.c src/modules/wm.c src/modules/theme.c src/modules/icons.c diff --git a/README.md b/README.md index 01422e7e5..a63700900 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ At the moment the performance difference is measurable, but too small to be huma ## Supported logos -Currently, `fastfetch` supports the `Arch` and the `Artix` logos only. Unknown/unsupported logos will be replaced with a question mark when running fastfetch. To add a new logo, edit [`src/logos.c`](src/logos.c). +Currently, `fastfetch` supports the `Arch` and the `Artix` logos only. Unknown/unsupported logos will be replaced with a question mark when running fastfetch. To add a new logo, edit [`src/logos.c`](src/logo.c). ## Dependencies diff --git a/completions/bash b/completions/bash index 492d25527..c52e999f7 100644 --- a/completions/bash +++ b/completions/bash @@ -6,8 +6,22 @@ __fastfetch_complete_help() "color" "os-format" "host-format" + "kernel-format" "packages-format" + "shell-format" + "resolution-format" + "de-format" + "wm-format" + "theme-format" + "icons-format" + "terminal-format" + "terminal-font-format" + "cpu-format" + "gpu-format" + "memory-format" + "disk-format" "battery-format" + "locale-format" ) COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD")) } @@ -95,16 +109,6 @@ __fastfetch_completion() "--recache" "--show-errors" "--color-logo" - "--os-architecture" - "--host-version" - "--kernel-release" - "--kernel-version" - "--packages-combined" - "--packages-combined-names" - "--packages-pacman" - "--packages-flatpak" - "--shell-path" - "--resolution-refreshrate" "--battery-manufacturer" "--battery-model" "--battery-technology" @@ -120,18 +124,33 @@ __fastfetch_completion() "--seperator" "-x" "--offsetx" - "--os-format" - "--host-format" - "--packages-format" - "--resolution-format" - "--battery-format" "--structure" "--set" + "--os-format" + "--host-format" + "--kernel-format" + "--uptime-format" + "--packages-format" + "--shell-format" + "--resolution-format" + "--de-format" + "--wm-format" + "--theme-format" + "--icons-format" + "--terminal-format" + "--terminal-font-format" + "--cpu-format" + "--gpu-format" + "--memory-format" + "--disk-format" + "--battery-format" + "--locale-format" ) local FF_OPTIONS_PATH=( - "--resolution-libX11" - "--resolution-libXrandr" + "--lib-PCI" + "--lib-X11" + "--lib-Xrandr" ) local FF_OPTIONS_LOGO=( diff --git a/src/common.c b/src/common.c index f6a233d15..712203150 100644 --- a/src/common.c +++ b/src/common.c @@ -5,6 +5,7 @@ #include #include #include +#include void ffInitState(FFstate* state) { @@ -12,15 +13,17 @@ void ffInitState(FFstate* state) state->passwd = getpwuid(getuid()); uname(&state->utsname); sysinfo(&state->sysinfo); - state->terminal.value = NULL; + + ffStrbufInit(&state->terminal.value); state->terminal.error = NULL; + state->terminal.calculated = false; } void ffDefaultConfig(FFconfig* config) { - config->color[0] = '\0'; + ffStrbufInit(&config->color); config->logo_spacer = 4; - strcpy(config->seperator, ": "); + ffStrbufInitS(&config->seperator, ": "); config->offsetx = 0; config->titleLength = 20; // This is overwritten by ffPrintTitle config->colorLogo = true; @@ -28,39 +31,35 @@ void ffDefaultConfig(FFconfig* config) config->recache = false; config->cacheSave = true; - config->osShowArchitecture = true; - config->osFormat[0] = '\0'; + ffStrbufInit(&config->osFormat); + ffStrbufInit(&config->hostFormat); + ffStrbufInit(&config->kernelFormat); + ffStrbufInit(&config->uptimeFormat); + ffStrbufInit(&config->packagesFormat); + ffStrbufInit(&config->shellFormat); + ffStrbufInit(&config->resolutionFormat); + ffStrbufInit(&config->deFormat); + ffStrbufInit(&config->wmFormat); + ffStrbufInit(&config->themeFormat); + ffStrbufInit(&config->iconsFormat); + ffStrbufInit(&config->fontFormat); + ffStrbufInit(&config->terminalFormat); + ffStrbufInit(&config->termFontFormat); + ffStrbufInit(&config->cpuFormat); + ffStrbufInit(&config->gpuFormat); + ffStrbufInit(&config->memoryFormat); + ffStrbufInit(&config->diskFormat); + ffStrbufInit(&config->batteryFormat); + ffStrbufInit(&config->localeFormat); - config->hostShowVersion = true; - config->hostFormat[0] = '\0'; - - config->kernelShowRelease = true; - config->kernelShowVersion = false; - - config->packagesCombined = false; - config->packagesCombinedNames = true; - config->packagesShowPacman = true; - config->packagesShowFlatpak = true; - config->packagesFormat[0] = '\0'; - - config->shellShowPath = false; - - config->resolutionShowRefreshRate = true; - config->resolutionLibX11[0] = '\0'; - config->resolutionLibXrandr[0] = '\0'; - config->resolutionFormat[0] = '\0'; - - config->batteryShowManufacturer = true; - config->batteryShowModel = true; - config->batteryShowTechnology = true; - config->batteryShowCapacity = true; - config->batteryShowStatus = true; - config->batteryFormat[0] = '\0'; + ffStrbufInitA(&config->libPCI, 256); + ffStrbufInitA(&config->libX11, 256); + ffStrbufInitA(&config->libXrandr, 256); } void ffPrintKey(FFconfig* config, const char* key) { - printf(FASTFETCH_TEXT_MODIFIER_BOLT"%s%s"FASTFETCH_TEXT_MODIFIER_RESET"%s", config->color, key, config->seperator); + printf(FASTFETCH_TEXT_MODIFIER_BOLT"%s%s"FASTFETCH_TEXT_MODIFIER_RESET"%s", config->color.chars, key, config->seperator.chars); } void ffPrintLogoAndKey(FFinstance* instance, const char* key) @@ -105,44 +104,44 @@ static inline bool strSet(const char* str) return str != NULL && str[0] != '\0'; } -void ffPrintGtkPretty(const char* gtk2, const char* gtk3, const char* gtk4) +void ffFormatGtkPretty(FFstrbuf* buffer, const char* gtk2, const char* gtk3, const char* gtk4) { if(strSet(gtk2) && strSet(gtk3) && strSet(gtk4)) { if((strcmp(gtk2, gtk3) == 0) && (strcmp(gtk2, gtk4) == 0)) - printf("%s [GTK2/3/4]", gtk2); + ffStrbufSetF(buffer, "%s [GTK2/3/4]", gtk2); else if(strcmp(gtk2, gtk3) == 0) - printf("%s [GTK2/3], %s [GTK4]", gtk2, gtk4); + ffStrbufSetF(buffer, "%s [GTK2/3], %s [GTK4]", gtk2, gtk4); else if(strcmp(gtk3, gtk4) == 0) - printf("%s [GTK2], %s [GTK3/4]", gtk2, gtk3); + ffStrbufSetF(buffer, "%s [GTK2], %s [GTK3/4]", gtk2, gtk3); else - printf("%s [GTK2], %s [GTK3], %s [GTK4]", gtk2, gtk3, gtk4); + ffStrbufSetF(buffer, "%s [GTK2], %s [GTK3], %s [GTK4]", gtk2, gtk3, gtk4); } else if(strSet(gtk2) && strSet(gtk3)) { if(strcmp(gtk2, gtk3) == 0) - printf("%s [GTK2/3]", gtk2); + ffStrbufSetF(buffer, "%s [GTK2/3]", gtk2); else - printf("%s [GTK2], %s [GTK3]", gtk2, gtk3); + ffStrbufSetF(buffer, "%s [GTK2], %s [GTK3]", gtk2, gtk3); } else if(strSet(gtk3) && strSet(gtk4)) { if(strcmp(gtk3, gtk4) == 0) - printf("%s [GTK3/4]", gtk3); + ffStrbufSetF(buffer, "%s [GTK3/4]", gtk3); else - printf("%s [GTK3], %s [GTK4]", gtk3, gtk4); + ffStrbufSetF(buffer, "%s [GTK3], %s [GTK4]", gtk3, gtk4); } else if(strSet(gtk2)) { - printf("%s [GTK2]", gtk2); + ffStrbufSetF(buffer, "%s [GTK2]", gtk2); } else if(strSet(gtk3)) { - printf("%s [GTK3]", gtk3); + ffStrbufSetF(buffer, "%s [GTK3]", gtk3); } else if(strSet(gtk4)) { - printf("%s [GTK4]", gtk4); + ffStrbufSetF(buffer, "%s [GTK4]", gtk4); } } @@ -160,13 +159,21 @@ void ffParseFont(char* font, char* buffer) sprintf(buffer, "%s (%spt)", name, size); } -void ffPrintError(FFinstance* instance, const char* key, const char* message) +void ffPrintError(FFinstance* instance, const char* key, const char* message, ...) { if(!instance->config.showErrors) return; ffPrintLogoAndKey(instance, key); - printf(FASTFETCH_TEXT_MODIFIER_ERROR"%s"FASTFETCH_TEXT_MODIFIER_RESET"\n", message); + + va_list arguments; + va_start(arguments, message); + + printf(FASTFETCH_TEXT_MODIFIER_ERROR); + vprintf(message, arguments); + puts(FASTFETCH_TEXT_MODIFIER_RESET); + + va_end(arguments); } void ffTrimTrailingWhitespace(char* buffer) @@ -237,12 +244,13 @@ bool ffPrintCachedValue(FFinstance* instance, const char* key) if(instance->config.recache) return false; - char fileName[256]; - strcpy(fileName, getCacheDir(instance)); - strcat(fileName, key); + FFstrbuf filename; + ffStrbufInitF(&filename, "%s%s", getCacheDir(instance), key); char value[1024]; - ffGetFileContent(fileName, value, sizeof(value)); + ffGetFileContent(filename.chars, value, sizeof(value)); + + ffStrbufDestroy(&filename); if(value[0] == '\0') return false; @@ -255,17 +263,15 @@ bool ffPrintCachedValue(FFinstance* instance, const char* key) void ffPrintAndSaveCachedValue(FFinstance* instance, const char* key, const char* value) { - ffPrintLogoAndKey(instance, key); puts(value); if(!instance->config.cacheSave) return; - char fileName[256]; - strcpy(fileName, getCacheDir(instance)); - strcat(fileName, key); + FFstrbuf filename; + ffStrbufInitF(&filename, "%s%s", getCacheDir(instance), key); - int fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int fd = open(filename.chars, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(fd == -1) return; @@ -276,5 +282,113 @@ void ffPrintAndSaveCachedValue(FFinstance* instance, const char* key, const char close(fd); if(failed) - unlink(fileName); + unlink(filename.chars); + + ffStrbufDestroy(&filename); } + +void ffParseFormatString(FFstrbuf* buffer, FFstrbuf* formatstr, uint32_t numArgs, ...) +{ + va_list argp; + va_start(argp, numArgs); + + FFformatarg arguments[numArgs]; + + for(uint32_t i = 0; i < numArgs; i++) + arguments[i] = (FFformatarg) va_arg(argp, FFformatarg); + + va_end(argp); + + uint32_t argCounter = 1; //First arg is 1 in fomat string + + for(uint32_t i = 0; i < formatstr->length; ++i) + { + if(formatstr->chars[i] != '{') + { + ffStrbufAppendC(buffer, formatstr->chars[i]); + continue; + } + + ++i; + + if(formatstr->chars[i] == '{') + { + ffStrbufAppendC(buffer, '{'); + continue; + } + + uint32_t argIndex; + + if(formatstr->chars[i] == '}') + { + argIndex = argCounter++; + } + else + { + FFstrbuf argnumstr; + ffStrbufInit(&argnumstr); + + while(true) + { + ffStrbufAppendC(&argnumstr, formatstr->chars[i++]); + + if(formatstr->chars[i] == '}') + break; + + if(formatstr->chars[i] == '\0') + { + fprintf(stderr, "Error: format string \"%s\" ends with an uncomplete placeholder %s\n", formatstr->chars, argnumstr.chars); + ffStrbufDestroy(buffer); + exit(802); + } + } + + if(ffStrbufGetC(&argnumstr, 0) == '-') + { + fprintf(stderr, "Error: format string \"%s\" placeholder value \"%s\" is negative\n", formatstr->chars, argnumstr.chars); + ffStrbufDestroy(buffer); + exit(803); + } + + if(sscanf(argnumstr.chars, "%u", &argIndex) != 1) + { + fprintf(stderr, "Error: format string \"%s\" placeholder value \"%s\" could not be parsed to uint32_t\n", formatstr->chars, argnumstr.chars); + ffStrbufDestroy(buffer); + exit(804); + } + + ffStrbufDestroy(&argnumstr); + } + + if(argIndex == 0) + argIndex = 1; + + if(argIndex > numArgs) + { + fprintf(stderr, "Error: format string \"%s\" placeholder {%u} wants higher argument than number of arguments (%u)\n", formatstr->chars, argIndex, numArgs); + ffStrbufDestroy(buffer); + exit(805); + } + + FFformatarg arg = arguments[argIndex - 1]; + + if(arg.type == FF_FORMAT_ARG_TYPE_INT) + ffStrbufAppendF(buffer, "%i", *(int*)arg.value); + else if(arg.type == FF_FORMAT_ARG_TYPE_UINT) + ffStrbufAppendF(buffer, "%u", *(uint32_t*)arg.value); + else if(arg.type == FF_FORMAT_ARG_TYPE_UINT8) + ffStrbufAppendF(buffer, "%u", *(uint8_t*)arg.value); + else if(arg.type == FF_FORMAT_ARG_TYPE_STRING) + ffStrbufAppendF(buffer, "%s", (const char*)arg.value); + else if(arg.type == FF_FORMAT_ARG_TYPE_STRBUF) + ffStrbufAppend(buffer, (FFstrbuf*)arg.value); + else if(arg.type == FF_FORMAT_ARG_TYPE_DOUBLE) + ffStrbufAppendF(buffer, "%.9g", *(double*)arg.value); + else + { + fprintf(stderr, "Error: format string \"%s\" argument is not implemented\n", formatstr->chars); + ffStrbufDestroy(buffer); + exit(806); + } + } +} \ No newline at end of file diff --git a/src/fastfetch.c b/src/fastfetch.c index 8514806fd..f0b8f98f8 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -11,63 +11,21 @@ #define FASTFETCH_DEFAULT_STRUCTURE "Title:Seperator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:Theme:Icons:Font:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors" #define FASTFETCH_DEFAULT_CONFIG \ - "## Fastfetch configuration\n" \ - "## Put arguments here to make them permanently.\n" \ - "## Direct arguments will overwrite the corresponding ones in this files\n" \ - "## Each line is whitespace trimmed on beginn and end.\n" \ - "## Empty lines or lines starting with # are ignored.\n" \ - "## There are more arguments possible than listed here, take a look at fastfetch --help!\n" \ - "## This version of the file was shipped with "FASTFETCH_PROJECT_VERSION".\n" \ - "## Use fastfetch --print-default-config > ~/.config/fastfetch/config.conf to generate a new one with current defaults.\n" \ - "\n" \ - "## General options:\n" \ - "# --structure "FASTFETCH_DEFAULT_STRUCTURE"\n" \ - "# --spacer 4\n" \ - "# --seperator \": \"\n" \ - "# --offsetx 0\n" \ - "# --recache false\n" \ - "# --show-errors false\n" \ - "\n" \ - "## Logo options:\n" \ - "# --color-logo true\n" \ - "\n" \ - "## OS options:\n" \ - "# --os-architecture true\n" \ - "\n" \ - "## Host options:\n" \ - "# --host-version true\n" \ - "\n" \ - "## Kernel options:\n" \ - "# --kernel-release true\n" \ - "# --kernel-version false\n" \ - "\n" \ - "## Packages options:\n" \ - "# --packages-combined false\n" \ - "# --packages-combined-names true\n" \ - "# --packages-pacman true\n" \ - "# --packages-flatpak true\n" \ - "\n" \ - "## Shell options:\n" \ - "# --shell-path false\n" \ - "\n" \ - "## Resolution options:\n" \ - "# --resolution-refreshrate true\n" \ - "# --resolution-libX11 libX11.so\n"\ - "# --resolution-libXrandr libXrandr.so\n" \ - "\n" \ - "## Battery options:\n" \ - "# --battery-manufacturer true\n" \ - "# --battery-model true\n" \ - "# --battery-technology true\n" \ - "# --battery-capacity true\n" \ - "# --battery-status true\n" + "# Fastfetch configuration\n" \ + "# Put arguments here to make them permanently (one per line). \n" \ + "# Direct arguments will overwrite the corresponding ones in this files\n" \ + "# Each line is whitespace trimmed on beginn and end.\n" \ + "# Empty lines or lines starting with # are ignored.\n" \ + "# There are more arguments possible than listed here, take a look at fastfetch --help!\n" \ + "# This version of the file was shipped with "FASTFETCH_PROJECT_VERSION".\n" \ + "# Use fastfetch --print-default-config > ~/.config/fastfetch/config.conf to generate a new one with current defaults.\n" //Things only needed by fastfetch typedef struct FFdata { FFvaluestore valuestore; - char structure[2048]; - char logoName[32]; + FFstrbuf structure; + FFstrbuf logoName; } FFdata; static inline void printHelp() @@ -97,41 +55,32 @@ static inline void printHelp() " -l , --logo : sets the shown logo. Also changes the main color accordingly\n" " --color-logo : if set to false, the logo will be black / white\n" "\n" - "OS options:\n" - " --os-architecture : Show the architecture of the os\n" - " --os-format : Provide the printf format string for os output (+)\n" + "Format options: Provide the format string for custom output (+)\n" + " --os-format \n" + " --host-format \n" + " --kernel-format \n" + " --uptime-format \n" + " --packages-format \n" + " --shell-format \n" + " --resolution-format \n" + " --de-format \n" + " --wm-format \n" + " --theme-format \n" + " --icons-format \n" + " --font-format \n" + " --terminal-format \n" + " --terminal-font-format \n" + " --cpu-format \n" + " --gpu-format \n" + " --memory-format \n" + " --disk-format \n" + " --battery-format \n" + " --locale-format \n" "\n" - "Host options:\n" - " --host-version : Show the version of the host platform, if possible. Most likely, this will be the BIOS version\n" - " --host-format : Provide the printf format string for host output (+)\n" - "\n" - "Kernel options:\n" - " --kernel-release : Shows the release of the kernel\n" - " --kernel-version : Shows the build version of the kernel\n" - "\n" - "Packages options:\n" - " --packages-combined : Show the sum of all packages\n" - " --packages-combined-names : Show the names of the package managers after the sum if in packages-combined mode\n" - " --packages-pacman : Count pacman packages\n" - " --packages-flatpak : Count flatpak packages\n" - " --packages-format : Provide the printf format string for packages output (+)\n" - "\n" - "Shell options:\n" - " --shell-path : Show the full path of the shell\n" - "\n" - "Resolution optins:\n" - " --resolution-refreshrate : Show the refresh rate of the monitor\n" - " --resolution-libX11 : Set the path to the x11 library to load\n" - " --resolution-libXrandr : Set the path to the xrandr library to load\n" - " --resolution-format : Provide the printf format string for resolution output (+)\n" - "\n" - "Battery options:\n" - " --battery-manufacturer : Show the manufacturer of the battery, if possible\n" - " --battery-model : Show the model of the battery, if possible\n" - " --battery-technology : Show the technology of the battery, if possible\n" - " --battery-capacity : Show the capacity of the battery, if possible\n" - " --battery-status : Show the status of the battery, if possible\n" - " --battery-format : Provide the printf format string for battery output (+)\n" + "Library optins: Set the path of a library to load\n" + " --lib-PCI \n" + " --lib-X11 :\n" + " --lib-Xrandr :\n" "\n" "If an value starts with an ?, it is optional. \"true\" will be used if not set.\n" "An (+) at the end indicates that more help can be printed with --help