diff --git a/completions/bash b/completions/bash index 7f0df66f5..ef2911913 100644 --- a/completions/bash +++ b/completions/bash @@ -5,6 +5,7 @@ __fastfetch_complete_help() local __ff_helps=( "color" "battery-format" + "packages-format" ) COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD")) } @@ -91,6 +92,10 @@ __fastfetch_completion() "--kernel-release" "--kernel-version" "--shell-path" + "--packages-combined" + "--packages-combined-names" + "--packages-pacman" + "--packages-flatpak" "--battery-manufacturer" "--battery-model" "--battery-technology" @@ -106,6 +111,7 @@ __fastfetch_completion() "--seperator" "-x" "--offsetx" + "--packages-format" "--battery-format" "--structure" "--set" diff --git a/src/common.c b/src/common.c index c6185e4f4..cd58a1b33 100644 --- a/src/common.c +++ b/src/common.c @@ -37,6 +37,12 @@ void ffDefaultConfig(FFconfig* config) config->shellShowPath = false; + config->packagesCombined = false; + config->packagesCombinedNames = true; + config->packagesPacman = true; + config->packagesFlatpak = true; + config->packagesFormat[0] = '\0'; + config->batteryShowManufacturer = true; config->batteryShowModel = true; config->batteryShowTechnology = true; diff --git a/src/fastfetch.c b/src/fastfetch.c index bfa986c3e..25d893921 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -44,6 +44,12 @@ "## Shell options:\n" \ "# --shell-path false\n" \ "\n" \ + "## Packages options:\n" \ + "# --packages-combined false\n" \ + "# --packages-combined-names true\n" \ + "# --packages-pacman true\n" \ + "# --packages-flatpak true\n" \ + "\n" \ "## Battery options:\n" \ "# --battery-manufacturer true\n" \ "# --battery-model true\n" \ @@ -59,7 +65,7 @@ typedef struct FFdata char logoName[32]; } FFdata; -static void printHelp() +static inline void printHelp() { puts( "Usage: fastfetch \n" @@ -99,6 +105,13 @@ static void printHelp() "Shell options:\n" " --shell-path : Show the full path of the shell\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" "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" @@ -141,17 +154,33 @@ static inline void printCommandHelpBatteryFormat() ); } -static void printCommandHelp(const char* command) +static inline void printCommandHelpPackagesFormat() +{ + puts( + "usage: fastfetch --packages-format \n" + "\n" + " is a string of maximum length 32, which is passed to printf as the format string.\n" + "if --packages-combined is set to false, the numbers of packages are passed to printf in following order as uint32_t:\n" + "pacman, flatpak\n" + "else, the total number of packages is passed as uint32_t\n" + "if an value is disabled via a packages-* argument, or could not be determined, zero is passed\n" + "The default value is something like \"%u (pacman), %u (flatpack)\"" + ); +} + +static inline void printCommandHelp(const char* command) { if(strcasecmp(command, "c") == 0 || strcasecmp(command, "color") == 0) printCommandHelpColor(); else if(strcasecmp(command, "battery-format") == 0) printCommandHelpBatteryFormat(); + else if(strcasecmp(command, "packages-format") == 0) + printCommandHelpPackagesFormat(); else printf("No specific help for command %s provided\n", command); } -static bool parseBoolean(const char* str) +static inline bool optionParseBoolean(const char* str) { if(str == NULL) return true; @@ -163,6 +192,22 @@ static bool parseBoolean(const char* str) ); } +static inline void optionParseString(const char* key, const char* value, char* target, uint32_t capacity) +{ + if(value == NULL) + { + printf("Error: usage: %s \n", key); + exit(477); + } + size_t len = strlen(value); + if(len > capacity) + { + printf("max string length for %s is %u, %zu given\n", key, capacity, len); + exit(478); + } + strcpy(target, value); +} + static void parseStructureCommand(FFinstance* instance, FFdata* data, const char* line) { const char* setValue = ffValuestoreGet(&data->valuestore, line); @@ -255,16 +300,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con puts(FASTFETCH_DEFAULT_CONFIG); exit(0); } - else if(strcasecmp(key, "-l") == 0 || strcasecmp(key, "--logo") == 0) - { - if(value == NULL) - { - printf("Error: usage: %s \n", key); - exit(401); - } - - strcpy(data->logoName, value); - } else if(strcasecmp(key, "-c") == 0 || strcasecmp(key, "--color") == 0) { if(value == NULL) @@ -293,21 +328,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con exit(405); } } - else if(strcasecmp(key, "-s") == 0 || strcasecmp(key, "--seperator") == 0) - { - if(value == NULL) - { - printf("Error: usage: %s \n", key); - exit(406); - } - size_t len = strlen(value); - if(len > 15) - { - printf("Error: max seperator length is 15, %zu given\n", len); - exit(407); - } - strcpy(instance->config.seperator, value); - } else if(strcasecmp(key, "-x") == 0 || strcasecmp(key, "--offsetx") == 0) { if(value == NULL) @@ -321,15 +341,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con exit(409); } } - else if(strcasecmp(key, "--structure") == 0) - { - if(value == NULL) - { - printf("Error: usage: %s \n", key); - exit(410); - } - strcpy(data->structure, value); - } else if(strcasecmp(key, "--set") == 0) { if(value == NULL) @@ -353,48 +364,51 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(strcasecmp(key, "-r") == 0 || strcasecmp(key, "--recache") == 0) { //Set cacheSave as well, beacuse the user expects the values to be cached when expliciting using --recache - instance->config.recache = parseBoolean(value); + instance->config.recache = optionParseBoolean(value); instance->config.cacheSave = instance->config.recache; } + else if(strcasecmp(key, "--structure") == 0) + optionParseString(key, value, data->structure, sizeof(data->structure)); + else if(strcasecmp(key, "-l") == 0 || strcasecmp(key, "--logo") == 0) + optionParseString(key, value, data->logoName, sizeof(instance->config.logo)); + else if(strcasecmp(key, "-s") == 0 || strcasecmp(key, "--seperator") == 0) + optionParseString(key, value, instance->config.seperator, sizeof(instance->config.seperator)); else if(strcasecmp(key, "--show-errors") == 0) - instance->config.showErrors = parseBoolean(value); + instance->config.showErrors = optionParseBoolean(value); else if(strcasecmp(key, "--color-logo") == 0) - instance->config.colorLogo = parseBoolean(value); + instance->config.colorLogo = optionParseBoolean(value); else if(strcasecmp(key, "--os-architecture") == 0) - instance->config.osShowArchitecture = parseBoolean(value); + instance->config.osShowArchitecture = optionParseBoolean(value); else if(strcasecmp(key, "--host-version") == 0) - instance->config.hostShowVersion = parseBoolean(value); + instance->config.hostShowVersion = optionParseBoolean(value); else if(strcasecmp(key, "--kernel-release") == 0) - instance->config.kernelShowRelease = parseBoolean(value); + instance->config.kernelShowRelease = optionParseBoolean(value); else if(strcasecmp(key, "--kernel-version") == 0) - instance->config.kernelShowVersion = parseBoolean(value); + instance->config.kernelShowVersion = optionParseBoolean(value); else if(strcasecmp(key, "--shell-path") == 0) - instance->config.shellShowPath = parseBoolean(value); + instance->config.shellShowPath = optionParseBoolean(value); + else if(strcasecmp(key, "--packages-combined") == 0) + instance->config.packagesCombined = optionParseBoolean(value); + else if(strcasecmp(key, "--packages-combined-names") == 0) + instance->config.packagesCombinedNames = optionParseBoolean(value); + else if(strcasecmp(key, "--packages-pacman") == 0) + instance->config.packagesPacman = optionParseBoolean(value); + else if(strcasecmp(key, "--packages-flatpak") == 0) + instance->config.packagesFlatpak = optionParseBoolean(value); + else if(strcasecmp(key, "--packages-format") == 0) + optionParseString(key, value, instance->config.packagesFormat, sizeof(instance->config.packagesFormat)); else if(strcasecmp(key, "--battery-manufacturer") == 0) - instance->config.batteryShowManufacturer = parseBoolean(value); + instance->config.batteryShowManufacturer = optionParseBoolean(value); else if(strcasecmp(key, "--battery-model") == 0) - instance->config.batteryShowModel = parseBoolean(value); + instance->config.batteryShowModel = optionParseBoolean(value); else if(strcasecmp(key, "--battery-technology") == 0) - instance->config.batteryShowTechnology = parseBoolean(value); + instance->config.batteryShowTechnology = optionParseBoolean(value); else if(strcasecmp(key, "--battery-capacity") == 0) - instance->config.batteryShowCapacity = parseBoolean(value); + instance->config.batteryShowCapacity = optionParseBoolean(value); else if(strcasecmp(key, "--battery-status") == 0) - instance->config.batteryShowStatus = parseBoolean(value); + instance->config.batteryShowStatus = optionParseBoolean(value); else if(strcasecmp(key, "--battery-format") == 0) - { - if(value == NULL) - { - printf("Error: usage: %s \n", key); - exit(413); - } - size_t len = strlen(value); - if(len > 32) - { - printf("max battery format string length is 32, %zu given\n", len); - exit(414); - } - strcpy(instance->config.batteryFormat, value); - } + optionParseString(key, value, instance->config.batteryFormat, sizeof(instance->config.batteryFormat)); else { printf("Error: unknown option: %s\n", key); diff --git a/src/fastfetch.h b/src/fastfetch.h index 96076e1f8..9b379f5dc 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -56,13 +56,20 @@ typedef struct FFconfig //Shell bool shellShowPath; + //Packages + bool packagesCombined; + bool packagesCombinedNames; + bool packagesPacman; + bool packagesFlatpak; + char packagesFormat[32]; + //Battery - char batteryFormat[32]; bool batteryShowManufacturer; bool batteryShowModel; bool batteryShowTechnology; bool batteryShowCapacity; bool batteryShowStatus; + char batteryFormat[32]; } FFconfig; diff --git a/src/modules/packages.c b/src/modules/packages.c index e2033867f..b7868bf14 100644 --- a/src/modules/packages.c +++ b/src/modules/packages.c @@ -23,17 +23,76 @@ static uint32_t get_num_dirs(const char* dirname) { return num_dirs; } - -static void printPacmanPackages() -{ - uint32_t nums = get_num_dirs("/var/lib/pacman/local"); - if(nums > 0) - printf("%i (pacman) ", nums); -} - void ffPrintPackages(FFinstance* instance) { + uint32_t pacman = instance->config.packagesPacman ? get_num_dirs("/var/lib/pacman/local") : 0; + uint32_t flatpak = instance->config.packagesFlatpak ? get_num_dirs("/var/lib/flatpak/app") : 0; + + uint32_t all = pacman + flatpak; + + if(all == 0) + { + ffPrintError(instance, "Packages", "No packages from known package managers found"); + return; + } + ffPrintLogoAndKey(instance, "Packages"); - printPacmanPackages(); - putchar('\n'); + + if(instance->config.packagesCombined) + { + if(instance->config.packagesFormat[0] != '\0') + { + printf(instance->config.packagesFormat, all); + putchar('\n'); + return; + } + + printf("%u", all); + + if(instance->config.packagesCombinedNames) + { + printf(" ("); + + #define FF_PRINT_PACKAGE(name) \ + if(name > 0) \ + { \ + printf(#name); \ + if((all = all - name) > 0) \ + printf(", "); \ + } \ + + FF_PRINT_PACKAGE(pacman) + FF_PRINT_PACKAGE(flatpak) + + #undef FF_PRINT_PACKAGE + + printf(")"); + } + + putchar('\n'); + } + else + { + if(instance->config.packagesFormat[0] != '\0') + { + printf(instance->config.packagesFormat, pacman, flatpak); + putchar('\n'); + return; + } + + #define FF_PRINT_PACKAGE(name) \ + if(name > 0) \ + { \ + printf("%u ("#name")", name); \ + if((all = all - name) > 0) \ + printf(", "); \ + }; + + FF_PRINT_PACKAGE(pacman) + FF_PRINT_PACKAGE(flatpak) + + #undef FF_PRINT_PACKAGE + + putchar('\n'); + } } \ No newline at end of file diff --git a/src/modules/terminal.c b/src/modules/terminal.c index 00443120f..8448bfe92 100644 --- a/src/modules/terminal.c +++ b/src/modules/terminal.c @@ -2,7 +2,7 @@ static void getTerminalName(FFinstance* instance, const char* pid, char* terminal, char* error) { - char file[256]; + char file[234]; sprintf(file, "/proc/%s/stat", pid); FILE* stat = fopen(file, "r"); diff --git a/src/modules/terminalfont.c b/src/modules/terminalfont.c index 37c6c81a4..d4621e60b 100644 --- a/src/modules/terminalfont.c +++ b/src/modules/terminalfont.c @@ -17,8 +17,8 @@ static void printKonsole(FFinstance* instance) ffParsePropFileHome(instance, profilePath, "Font=%[^\n]", font); if(font[0] == '\0') { - char error[256]; - sprintf(error, "Terminal Font", "Couldn't find \"Font=%[^\n]\" in \"%s\"", profilePath); + char error[289]; + sprintf(error, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath); ffPrintError(instance, "Terminal Font", error); } diff --git a/tests/performance.c b/tests/performance.c index a6dbf4e9c..9eb418640 100644 --- a/tests/performance.c +++ b/tests/performance.c @@ -45,6 +45,7 @@ int main(int argc, char** argv) FASTFETCH_TEST_PERFORMANCE(ffPrintIcons(&instance)) FASTFETCH_TEST_PERFORMANCE(ffPrintFont(&instance)) FASTFETCH_TEST_PERFORMANCE(ffPrintTerminal(&instance)) + FASTFETCH_TEST_PERFORMANCE(ffPrintTerminalFont(&instance)) FASTFETCH_TEST_PERFORMANCE(ffPrintCPU(&instance)) FASTFETCH_TEST_PERFORMANCE(ffPrintGPU(&instance)) FASTFETCH_TEST_PERFORMANCE(ffPrintMemory(&instance))