Files
fastfetch/src/fastfetch.c
T

945 lines
32 KiB
C
Raw Normal View History

2021-02-18 22:25:36 +01:00
#include "fastfetch.h"
#include "util/FFvaluestore.h"
2021-02-18 22:25:36 +01:00
2021-04-09 14:07:05 +02:00
#include <string.h>
2021-02-27 20:31:54 +01:00
#include <malloc.h>
2021-02-27 20:50:13 +01:00
#include <unistd.h>
2021-02-27 20:31:54 +01:00
#include <sys/stat.h>
2021-02-27 20:50:13 +01:00
#include <fcntl.h>
2021-04-25 11:48:25 +02:00
#include <dirent.h>
2021-02-22 16:52:51 +01:00
2021-06-13 17:44:34 +05:30
// Things only needed by fastfetch
typedef struct FFdata
{
FFvaluestore valuestore;
2021-03-19 20:57:07 +01:00
FFstrbuf structure;
FFstrbuf logoName;
2021-04-07 17:36:03 +02:00
bool multithreading;
} FFdata;
2021-03-21 11:18:06 +01:00
static void constructAndPrintCommandHelpFormat(const char* name, const char* def, uint32_t numArgs, ...)
2021-03-19 20:57:07 +01:00
{
2021-03-21 11:18:06 +01:00
va_list argp;
va_start(argp, numArgs);
2021-03-19 20:57:07 +01:00
2021-03-21 11:18:06 +01:00
printf("--%s-format:\n", name);
printf("Sets the format string for %s output.\n", name);
puts("To see how a format string is constructed, take a look at \"fastfetch --help format\".");
2021-05-15 08:39:20 +02:00
puts("The following values are passed:");
2021-03-19 20:57:07 +01:00
2021-03-21 11:18:06 +01:00
for(uint32_t i = 1; i <= numArgs; i++)
printf(" {%u}: %s\n", i, va_arg(argp, const char*));
2021-03-19 20:57:07 +01:00
2021-03-21 11:18:06 +01:00
printf("The default is something like \"%s\".\n", def);
2021-03-19 20:57:07 +01:00
2021-03-21 11:18:06 +01:00
va_end(argp);
2021-03-11 22:15:48 +01:00
}
2021-03-11 19:40:46 +01:00
static inline void printCommandHelp(const char* command)
2021-02-20 19:32:57 +01:00
{
2021-10-22 21:53:29 +02:00
if(command == NULL)
fputs(FASTFETCH_DATATEXT_HELP, stdout);
else if(strcasecmp(command, "c") == 0 || strcasecmp(command, "color") == 0)
fputs(FASTFETCH_DATATEXT_HELP_COLOR, stdout);
2021-03-21 11:18:06 +01:00
else if(strcasecmp(command, "format") == 0)
2021-10-22 21:53:29 +02:00
fputs(FASTFETCH_DATATEXT_HELP_FORMAT, stdout);
else if(strcasecmp(command, "load-config") == 0 || strcasecmp(command, "loadconfig") == 0 || strcasecmp(command, "config") == 0)
fputs(FASTFETCH_DATATEXT_HELP_CONFIG, stdout);
2021-03-12 10:17:49 +01:00
else if(strcasecmp(command, "os-format") == 0)
2021-03-27 17:48:32 +01:00
{
constructAndPrintCommandHelpFormat("os", "{3} {12}", 12,
2021-05-15 08:39:20 +02:00
"System name (typically just Linux)",
2021-03-27 17:48:32 +01:00
"Name of the OS",
"Pretty name of the OS",
"ID of the OS",
"ID like of the OS",
"Variant of the OS",
"Variant ID of the OS",
"Version of the OS",
"Version ID of the OS",
"Version codename of the OS",
"Build ID of the OS",
"Architecture of the OS"
);
}
2021-03-12 12:16:41 +01:00
else if(strcasecmp(command, "host-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-14 16:03:19 +02:00
constructAndPrintCommandHelpFormat("host", "{2} {3}", 3,
2021-04-03 11:39:59 +02:00
"Host family",
"Host name",
"Host version"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "kernel-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("kernel", "{2}", 3,
"Kernel sysname",
"Kernel release",
"Kernel version"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "uptime-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("uptime", "{} days {} hours {} mins", 4,
"Days",
"Hours",
"Minutes",
"Seconds"
);
}
2021-10-18 22:38:00 +08:00
else if(strcasecmp(command, "processes-format") == 0)
{
constructAndPrintCommandHelpFormat("processes", "{}", 1,
"Count"
);
}
2021-03-11 19:40:46 +01:00
else if(strcasecmp(command, "packages-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-06-08 20:01:29 +02:00
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (xps), {7}, (flatpak), {8} (snap)", 8,
2021-04-03 11:39:59 +02:00
"Number of all packages",
"Number of pacman packages",
2021-05-15 18:17:34 +02:00
"Pacman branch on manjaro",
2021-05-01 21:22:07 +02:00
"Number of dpkg packages",
2021-06-08 20:01:29 +02:00
"Number of rpm packages",
"Number of xbps packages",
2021-04-28 19:45:43 +02:00
"Number of flatpak packages",
2021-05-01 21:22:07 +02:00
"Number of snap packages"
2021-04-03 11:39:59 +02:00
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "shell-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-06-14 23:22:14 +02:00
constructAndPrintCommandHelpFormat("shell", "{3} {4}", 7,
"Shell process name",
"Shell path with exe name",
"Shell exe name",
"Shell version",
"User shell path with exe name",
"User shell exe name",
"User shell version"
2021-04-03 11:39:59 +02:00
);
}
2021-03-11 22:15:48 +01:00
else if(strcasecmp(command, "resolution-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("resolution", "{}x{} @ {}Hz", 3,
"Screen width",
"Screen height",
"Screen refresh rate"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "de-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-01 13:03:30 +02:00
constructAndPrintCommandHelpFormat("de", "{3} {4}", 4,
2021-04-25 21:32:35 +02:00
"Session desktop",
2021-05-01 13:03:30 +02:00
"DE process name",
"DE pretty name",
"DE version"
2021-04-03 11:39:59 +02:00
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "wm-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-01 13:03:30 +02:00
constructAndPrintCommandHelpFormat("wm", "{3} ({4})", 4,
"Session desktop",
2021-04-03 11:39:59 +02:00
"WM process name",
2021-04-25 21:32:35 +02:00
"WM pretty name",
"WM protocol name"
2021-04-03 11:39:59 +02:00
);
}
2021-04-03 23:10:14 +02:00
else if(strcasecmp(command, "wm-theme-format") == 0)
{
constructAndPrintCommandHelpFormat("wm-theme", "{}", 1,
"WM theme name"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "theme-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-04-09 19:21:56 +02:00
constructAndPrintCommandHelpFormat("theme", "{} ({3}) [Plasma], {7}", 7,
2021-04-03 11:39:59 +02:00
"Plasma theme",
2021-04-09 19:21:56 +02:00
"Plasma color scheme",
"Plasma color scheme pretty",
2021-04-03 11:39:59 +02:00
"GTK2 theme",
"GTK3 theme",
"GTK4 theme",
"Combined GTK themes"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "icons-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("icons", "{} [Plasma], {5}", 5,
"Plasma icons",
"GTK2 icons",
"GTK3 icons",
"GTK4 icons",
"Combined GTK icons"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "font-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-23 19:40:34 +02:00
constructAndPrintCommandHelpFormat("font", "{5} [Plasma], {21}", 21,
"Plasma raw",
2021-04-05 19:25:34 +02:00
"Plasma name",
"Plasma size",
2021-05-23 19:40:34 +02:00
"Plasma styles",
"Plasma pretty",
"GTK2 raw",
2021-04-05 19:25:34 +02:00
"GTK2 name",
"GTK2 size",
2021-05-23 19:40:34 +02:00
"GTK2 styles",
"GTK2 pretty",
"GTK3 raw",
2021-04-05 19:25:34 +02:00
"GTK3 name",
"GTK3 size",
2021-05-23 19:40:34 +02:00
"GTK3 styles",
"GTK3 pretty",
"GTK4 raw",
2021-04-05 19:25:34 +02:00
"GTK4 name",
"GTK4 size",
2021-05-23 19:40:34 +02:00
"GTK4 styles",
"GTK4 pretty",
"GTK2/3/4 pretty"
2021-04-03 11:39:59 +02:00
);
}
2021-06-20 21:04:55 +02:00
else if(strcasecmp(command, "cursor-format") == 0)
{
constructAndPrintCommandHelpFormat("cursor", "{} ({}pt)", 2,
"Cursor theme",
"Cursor size"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "terminal-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("terminal", "{3}", 3,
"Terminal process name",
2021-06-14 23:22:14 +02:00
"Terminal path with exe name",
"Terminal exe name"
2021-04-03 11:39:59 +02:00
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "terminal-font-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-23 19:40:34 +02:00
constructAndPrintCommandHelpFormat("terminal-font", "{5}", 5,
"Terminal font raw",
2021-04-05 19:25:34 +02:00
"Terminal font name",
"Termianl font size",
2021-05-23 19:40:34 +02:00
"Terminal font styles"
"Terminal font pretty"
2021-04-03 11:39:59 +02:00
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "cpu-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-06-16 11:28:33 +02:00
constructAndPrintCommandHelpFormat("cpu", "{2} ({7}) @ {14}GHz", 14,
2021-04-03 11:39:59 +02:00
"CPU name",
"Prettified CPU name",
"CPU Vendor name (Vendor ID)",
"CPU logical core count online",
"CPU logical core count configured",
"CPU physical core count",
2021-04-15 18:59:26 +02:00
"Always set core count",
2021-04-03 11:39:59 +02:00
"frequency bios limit",
"frequency scaling max",
"frequency scaling min",
"frequency info max",
2021-04-03 21:51:50 +02:00
"frequency info min",
2021-06-16 11:28:33 +02:00
"frequeny from /proc/cpuinfo",
"most accurate frequeny"
2021-04-03 11:39:59 +02:00
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "gpu-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-07 17:10:22 +02:00
constructAndPrintCommandHelpFormat("gpu", "{2} {4}", 4,
2021-04-03 11:39:59 +02:00
"GPU vendor",
2021-05-05 19:31:58 +02:00
"GPU vendor pretty",
2021-05-07 17:10:22 +02:00
"GPU name",
"GPU name pretty"
2021-04-03 11:39:59 +02:00
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "memory-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("memory", "{}MiB / {}MiB ({}%)", 3,
"Used memory",
"Total memory",
"Used memory percentage"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "disk-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("disk", "{}GB / {}GB ({4}%)", 4,
"Used disk space",
"Total disk space",
"Number of files",
"Used disk space percentage"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "battery-format") == 0)
2021-04-03 11:39:59 +02:00
{
2021-05-30 21:35:04 +02:00
constructAndPrintCommandHelpFormat("battery", "{}%, {}", 5,
2021-04-03 11:39:59 +02:00
"Battery manufactor",
"Battery model",
"Battery technology",
"Battery capacity",
"Battery status"
);
}
2021-03-19 20:57:07 +01:00
else if(strcasecmp(command, "locale-format") == 0)
2021-04-03 11:39:59 +02:00
{
constructAndPrintCommandHelpFormat("locale", "{}", 1,
"Locale code"
);
}
2021-02-20 19:32:57 +01:00
else
2021-04-03 11:39:59 +02:00
fprintf(stderr, "No specific help for command %s provided\n", command);
2021-02-20 19:32:57 +01:00
}
2021-04-25 11:48:25 +02:00
static inline void listAvailablePresetsFromFolder(FFstrbuf* folder, uint8_t indentation, const char* folderName)
{
DIR* dir = opendir(folder->chars);
if(dir == NULL)
return;
uint32_t folderLength = folder->length;
if(folderName != NULL)
printf("%s/\n", folderName);
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_type == DT_DIR)
{
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
ffStrbufAppendS(folder, entry->d_name);
ffStrbufAppendC(folder, '/');
listAvailablePresetsFromFolder(folder, indentation + 1, entry->d_name);
ffStrbufSubstrBefore(folder, folderLength);
continue;
}
for(uint8_t i = 0; i < indentation; i++)
fputs(" | ", stdout);
puts(entry->d_name);
}
closedir(dir);
}
static inline void listAvailablePresets(FFinstance* instance)
{
FFstrbuf folder;
ffStrbufInitA(&folder, 64);
ffStrbufSetS(&folder, instance->state.passwd->pw_dir);
ffStrbufAppendS(&folder, "/.local/share/fastfetch/presets/");
listAvailablePresetsFromFolder(&folder, 0, NULL);
ffStrbufSetS(&folder, "/usr/share/fastfetch/presets/");
listAvailablePresetsFromFolder(&folder, 0, NULL);
2021-04-25 15:07:31 +02:00
ffStrbufDestroy(&folder);
2021-04-25 11:48:25 +02:00
}
static inline void listSupportedFeatures()
{
fputs(
#ifdef FF_HAVE_LIBPCI
"libpci\n"
#endif
#ifdef FF_HAVE_X11
"x11\n"
#endif
#ifdef FF_HAVE_XRANDR
"xrandr\n"
#endif
#ifdef FF_HAVE_WAYLAND
"wayland\n"
#endif
#ifdef FF_HAVE_GIO
"gio\n"
#endif
#ifdef FF_HAVE_DCONF
"dconf\n"
#endif
#ifdef FF_HAVE_XFCONF
"xfconf\n"
#endif
#ifdef FF_HAVE_SQLITE3
"sqlite3\n"
#endif
""
, stdout);
}
2021-04-25 11:48:25 +02:00
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value);
static void parseConfigFile(FFinstance* instance, FFdata* data, FILE* file)
{
char* lineStart = NULL;
size_t len = 0;
ssize_t read;
FFstrbuf line;
ffStrbufInitA(&line, 128); //The default structure line needs this size
while ((read = getline(&lineStart, &len, file)) != -1)
{
ffStrbufSetS(&line, lineStart);
ffStrbufTrimRight(&line, '\n');
ffStrbufTrim(&line, ' ');
if(line.length == 0 || line.chars[0] == '#')
continue;
uint32_t firstSpace = ffStrbufFirstIndexC(&line, ' ');
if(firstSpace >= line.length)
{
parseOption(instance, data, line.chars, NULL);
continue;
}
2021-05-15 08:39:20 +02:00
//Separate key and value by simply replacing the first space with a \0
2021-04-25 11:48:25 +02:00
char* valueStart = &line.chars[firstSpace];
*valueStart = '\0';
++valueStart;
2021-05-15 08:39:20 +02:00
//Trim whitespace at beginning of value
2021-04-25 11:48:25 +02:00
while(*valueStart == ' ')
++valueStart;
//If we want whitespace in values, we need to quote it. This is done to keep consistency with shell.
if(*valueStart == '"')
{
char* last = line.chars + line.length - 1;
if(*last == '"')
{
++valueStart;
*last = '\0';
--line.length;
}
}
parseOption(instance, data, line.chars, valueStart);
}
ffStrbufDestroy(&line);
if(lineStart != NULL)
free(lineStart);
}
static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char* key, const char* value)
{
if(value == NULL)
{
fprintf(stderr, "Error: usage: %s <file>\n", key);
exit(413);
}
FILE* file = fopen(value, "r");
if(file != NULL)
{
parseConfigFile(instance, data, file);
fclose(file);
return;
}
FFstrbuf filename;
ffStrbufInitA(&filename, 64);
ffStrbufAppendS(&filename, instance->state.passwd->pw_dir);
ffStrbufAppendS(&filename, "/.local/share/fastfetch/presets/");
ffStrbufAppendS(&filename, value);
file = fopen(filename.chars, "r");
if(file != NULL)
{
parseConfigFile(instance, data, file);
fclose(file);
return;
}
ffStrbufSetS(&filename, "/usr/share/fastfetch/presets/");
ffStrbufAppendS(&filename, value);
file = fopen(filename.chars, "r");
if(file != NULL)
{
parseConfigFile(instance, data, file);
fclose(file);
return;
}
fprintf(stderr, "Error: couldn't find config: %s\n", value);
exit(414);
}
2021-03-11 19:40:46 +01:00
static inline bool optionParseBoolean(const char* str)
2021-02-27 20:31:54 +01:00
{
2021-03-07 20:35:17 +01:00
return (
2021-05-09 21:41:17 +02:00
str == NULL ||
*str == '\0' ||
strcasecmp(str, "true") == 0 ||
strcasecmp(str, "yes") == 0 ||
2021-04-07 17:36:03 +02:00
strcasecmp(str, "on") == 0 ||
strcasecmp(str, "1") == 0
2021-03-07 20:35:17 +01:00
);
2021-02-27 20:31:54 +01:00
}
2021-03-19 20:57:07 +01:00
static inline void optionParseString(const char* key, const char* value, FFstrbuf* buffer)
2021-03-11 19:40:46 +01:00
{
if(value == NULL)
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: usage: %s <str>\n", key);
2021-03-11 19:40:46 +01:00
exit(477);
}
2021-05-15 08:39:20 +02:00
ffStrbufEnsureCapacity(buffer, 64); //This is not needed, as ffStrbufSetS will resize capacity if needed, but giving a higher start should improve performance
2021-03-19 20:57:07 +01:00
ffStrbufSetS(buffer, value);
2021-02-27 20:31:54 +01:00
}
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value)
2021-02-27 20:31:54 +01:00
{
if(strcasecmp(key, "-h") == 0 || strcasecmp(key, "--help") == 0)
{
2021-10-22 21:53:29 +02:00
printCommandHelp(value);
exit(0);
}
else if(strcasecmp(key, "-v") == 0 || strcasecmp(key, "--version") == 0)
{
2021-03-05 21:49:13 +01:00
puts(FASTFETCH_PROJECT_NAME" "FASTFETCH_PROJECT_VERSION);
exit(0);
}
else if(strcasecmp(key, "--list-logos") == 0)
{
ffListLogos();
exit(0);
}
else if(strcasecmp(key, "--print-logos") == 0)
{
2021-06-13 14:23:35 +02:00
ffPrintLogos(instance);
exit(0);
}
2021-10-23 14:59:11 +02:00
else if(strcasecmp(key, "--print-config") == 0)
{
2021-10-22 21:53:29 +02:00
fputs(FASTFETCH_DATATEXT_CONFIG, stdout);
exit(0);
}
2021-10-23 14:59:11 +02:00
else if(strcasecmp(key, "--print-structure") == 0)
2021-03-27 19:26:58 +01:00
{
2021-10-23 14:59:11 +02:00
puts(FASTFETCH_DATATEXT_STRUCTURE);
2021-03-27 19:26:58 +01:00
exit(0);
}
2021-10-23 14:59:11 +02:00
else if(strcasecmp(key, "--list-modules") == 0)
2021-03-27 19:26:58 +01:00
{
2021-10-22 21:53:29 +02:00
fputs(FASTFETCH_DATATEXT_MODULES, stdout);
2021-03-27 19:26:58 +01:00
exit(0);
}
2021-10-23 14:59:11 +02:00
else if(strcasecmp(key, "--list-presets") == 0)
2021-04-25 11:48:25 +02:00
{
listAvailablePresets(instance);
exit(0);
}
2021-10-23 14:59:11 +02:00
else if(strcasecmp(key, "--list-features") == 0)
{
listSupportedFeatures();
exit(0);
}
2021-03-21 17:02:31 +01:00
else if(strcasecmp(key, "--spacing") == 0)
{
if(value == NULL)
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: usage: %s <width>\n", key);
2021-03-05 23:00:28 +01:00
exit(404);
}
2021-06-13 14:23:35 +02:00
if(sscanf(value, "%hu", &instance->config.logoKeySpacing) != 1)
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: couldn't parse %s to uint16_t\n", value);
2021-03-05 23:00:28 +01:00
exit(405);
}
}
else if(strcasecmp(key, "-x") == 0 || strcasecmp(key, "--offsetx") == 0)
{
if(value == NULL)
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: usage: %s <offset>\n", key);
2021-03-05 23:00:28 +01:00
exit(408);
}
if(sscanf(value, "%hi", &instance->config.offsetx) != 1)
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: couldn't parse %s to int16_t\n", value);
2021-03-05 23:00:28 +01:00
exit(409);
}
}
else if(strcasecmp(key, "--set") == 0)
{
if(value == NULL)
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: usage: %s <key=value>\n", key);
2021-03-05 23:00:28 +01:00
exit(411);
}
2021-05-15 12:36:25 +02:00
char* separator = strchr(value, '=');
2021-03-05 23:00:28 +01:00
2021-05-15 12:36:25 +02:00
if(separator == NULL)
2021-03-05 23:00:28 +01:00
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: usage: %s <key=value>, '=' missing\n", key);
2021-03-05 23:00:28 +01:00
exit(412);
}
2021-05-15 12:36:25 +02:00
*separator = '\0';
2021-05-15 12:36:25 +02:00
ffValuestoreSet(&data->valuestore, value, separator + 1);
}
else if(strcasecmp(key, "-r") == 0 || strcasecmp(key, "--recache") == 0)
{
2021-05-15 08:39:20 +02:00
//Set cacheSave as well, beacuse the user expects the values to be cached when expliciting using --recache
2021-03-11 19:40:46 +01:00
instance->config.recache = optionParseBoolean(value);
2021-03-07 20:35:17 +01:00
instance->config.cacheSave = instance->config.recache;
2021-03-06 11:28:38 +01:00
}
2021-04-18 19:23:54 +02:00
else if(strcasecmp(key, "--nocache") == 0)
{
instance->config.recache = optionParseBoolean(value);
instance->config.cacheSave = false;
}
2021-04-25 11:48:25 +02:00
else if(strcasecmp(key, "--load-config") == 0)
optionParseConfigFile(instance, data, key, value);
2021-03-07 20:35:17 +01:00
else if(strcasecmp(key, "--show-errors") == 0)
2021-03-11 19:40:46 +01:00
instance->config.showErrors = optionParseBoolean(value);
2021-03-07 20:35:17 +01:00
else if(strcasecmp(key, "--color-logo") == 0)
2021-03-11 19:40:46 +01:00
instance->config.colorLogo = optionParseBoolean(value);
2021-03-19 21:23:15 +01:00
else if(strcasecmp(key, "--print-remaining-logo") == 0)
instance->config.printRemainingLogo = optionParseBoolean(value);
2021-04-07 17:36:03 +02:00
else if(strcasecmp(key, "--multithreading") == 0)
data->multithreading = optionParseBoolean(value);
2021-05-09 21:41:17 +02:00
else if(strcasecmp(key, "--allow-slow-operations") == 0)
instance->config.allowSlowOperations = optionParseBoolean(value);
2021-06-17 13:49:25 +02:00
else if(strcasecmp(key, "--disable-linewrap") == 0)
instance->config.disableLinewrap = optionParseBoolean(value);
else if(strcasecmp(key, "--hide-cursor") == 0)
instance->config.hideCursor = optionParseBoolean(value);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--structure") == 0)
optionParseString(key, value, &data->structure);
2021-06-13 14:23:35 +02:00
else if(strcasecmp(key, "-l") == 0 || strcasecmp(key, "--logo") == 0)
2021-03-19 20:57:07 +01:00
optionParseString(key, value, &data->logoName);
2021-05-15 12:36:25 +02:00
else if(strcasecmp(key, "-s") == 0 || strcasecmp(key, "--separator") == 0)
optionParseString(key, value, &instance->config.separator);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "-c") == 0 || strcasecmp(key, "--color") == 0)
2021-05-27 14:56:31 +02:00
{
if(value == NULL)
{
fprintf(stderr, "Error: usage: %s <str>\n", key);
exit(477);
}
ffStrbufSetS(&instance->config.color, "\033[");
ffStrbufAppendS(&instance->config.color, value);
ffStrbufAppendC(&instance->config.color, 'm');
}
2021-03-12 10:17:49 +01:00
else if(strcasecmp(key, "--os-format") == 0)
2021-03-19 20:57:07 +01:00
optionParseString(key, value, &instance->config.osFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--os-key") == 0)
optionParseString(key, value, &instance->config.osKey);
2021-03-12 12:16:41 +01:00
else if(strcasecmp(key, "--host-format") == 0)
2021-03-19 20:57:07 +01:00
optionParseString(key, value, &instance->config.hostFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--host-key") == 0)
optionParseString(key, value, &instance->config.hostKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--kernel-format") == 0)
optionParseString(key, value, &instance->config.kernelFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--kernel-key") == 0)
optionParseString(key, value, &instance->config.kernelKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--uptime-format") == 0)
optionParseString(key, value, &instance->config.uptimeFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--uptime-key") == 0)
optionParseString(key, value, &instance->config.uptimeKey);
2021-10-18 22:38:00 +08:00
else if(strcasecmp(key, "--processes-format") == 0)
optionParseString(key, value, &instance->config.processesFormat);
else if(strcasecmp(key, "--processes-key") == 0)
optionParseString(key, value, &instance->config.processesKey);
2021-03-11 19:40:46 +01:00
else if(strcasecmp(key, "--packages-format") == 0)
2021-03-19 20:57:07 +01:00
optionParseString(key, value, &instance->config.packagesFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--packages-key") == 0)
optionParseString(key, value, &instance->config.packagesKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--shell-format") == 0)
optionParseString(key, value, &instance->config.shellFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--shell-key") == 0)
optionParseString(key, value, &instance->config.shellKey);
2021-03-11 22:15:48 +01:00
else if(strcasecmp(key, "--resolution-format") == 0)
2021-03-19 20:57:07 +01:00
optionParseString(key, value, &instance->config.resolutionFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--resolution-key") == 0)
optionParseString(key, value, &instance->config.resolutionKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--de-format") == 0)
optionParseString(key, value, &instance->config.deFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--de-key") == 0)
optionParseString(key, value, &instance->config.deKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--wm-format") == 0)
optionParseString(key, value, &instance->config.wmFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--wm-key") == 0)
optionParseString(key, value, &instance->config.wmKey);
2021-04-03 23:10:14 +02:00
else if(strcasecmp(key, "--wm-theme-format") == 0)
optionParseString(key, value, &instance->config.wmThemeFormat);
else if(strcasecmp(key, "--wm-theme-key") == 0)
optionParseString(key, value, &instance->config.wmThemeKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--theme-format") == 0)
optionParseString(key, value, &instance->config.themeFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--theme-key") == 0)
optionParseString(key, value, &instance->config.themeKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--icons-format") == 0)
optionParseString(key, value, &instance->config.iconsFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--icons-key") == 0)
optionParseString(key, value, &instance->config.iconsKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--font-format") == 0)
optionParseString(key, value, &instance->config.fontFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--font-key") == 0)
optionParseString(key, value, &instance->config.fontKey);
2021-06-20 21:04:55 +02:00
else if(strcasecmp(key, "--cursor-key") == 0)
optionParseString(key, value, &instance->config.cursorKey);
else if(strcasecmp(key, "--cursor-format") == 0)
optionParseString(key, value, &instance->config.cursorFormat);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--terminal-format") == 0)
optionParseString(key, value, &instance->config.terminalFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--terminal-key") == 0)
optionParseString(key, value, &instance->config.terminalKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--terminal-font-format") == 0)
optionParseString(key, value, &instance->config.termFontFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--terminal-font-key") == 0)
optionParseString(key, value, &instance->config.termFontKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--cpu-format") == 0)
optionParseString(key, value, &instance->config.cpuFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--cpu-key") == 0)
optionParseString(key, value, &instance->config.cpuKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--gpu-format") == 0)
optionParseString(key, value, &instance->config.gpuFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--gpu-key") == 0)
optionParseString(key, value, &instance->config.gpuKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--memory-format") == 0)
optionParseString(key, value, &instance->config.memoryFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--memory-key") == 0)
optionParseString(key, value, &instance->config.memoryKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--disk-format") == 0)
optionParseString(key, value, &instance->config.diskFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--disk-key") == 0)
optionParseString(key, value, &instance->config.diskKey);
2021-03-04 20:49:12 +01:00
else if(strcasecmp(key, "--battery-format") == 0)
2021-03-19 20:57:07 +01:00
optionParseString(key, value, &instance->config.batteryFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--battery-key") == 0)
optionParseString(key, value, &instance->config.batteryKey);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--locale-format") == 0)
optionParseString(key, value, &instance->config.localeFormat);
2021-04-03 11:39:59 +02:00
else if(strcasecmp(key, "--locale-key") == 0)
optionParseString(key, value, &instance->config.localeKey);
2021-10-17 12:42:15 +08:00
else if(strcasecmp(key, "--local-ip-key") == 0)
optionParseString(key, value, &instance->config.localIpKey);
else if(strcasecmp(key, "--local-ip-format") == 0)
optionParseString(key, value, &instance->config.localIpFormat);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(key, "--lib-PCI") == 0)
optionParseString(key, value, &instance->config.libPCI);
else if(strcasecmp(key, "--lib-X11") == 0)
optionParseString(key, value, &instance->config.libX11);
else if(strcasecmp(key, "--lib-Xrandr") == 0)
optionParseString(key, value, &instance->config.libXrandr);
2021-05-02 18:52:42 +02:00
else if(strcasecmp(key, "--lib-gio") == 0)
optionParseString(key, value, &instance->config.libGIO);
2021-04-05 23:42:07 +02:00
else if(strcasecmp(key, "--lib-DConf") == 0)
optionParseString(key, value, &instance->config.libDConf);
2021-04-16 16:49:33 +02:00
else if(strcasecmp(key, "--lib-wayland") == 0)
optionParseString(key, value, &instance->config.libWayland);
2021-05-11 20:06:17 +02:00
else if(strcasecmp(key, "--lib-XFConf") == 0)
optionParseString(key, value, &instance->config.libXFConf);
2021-06-08 20:01:29 +02:00
else if(strcasecmp(key, "--lib-SQLite") == 0)
optionParseString(key, value, &instance->config.libSQLite);
2021-03-28 15:38:52 +02:00
else if(strcasecmp(key, "--disk-folders") == 0)
optionParseString(key, value, &instance->config.diskFolders);
2021-04-24 13:05:43 +02:00
else if(strcasecmp(key, "--battery-dir") == 0)
optionParseString(key, value, &instance->config.batteryDir);
2021-10-17 12:42:15 +08:00
else if(strcasecmp(key, "--localip-show-ipv4") == 0)
instance->config.localIpShowIpV4 = optionParseBoolean(value);
else if(strcasecmp(key, "--localip-show-ipv6") == 0)
instance->config.localIpShowIpV6 = optionParseBoolean(value);
else if(strcasecmp(key, "--localip-show-loop") == 0)
instance->config.localIpShowLoop = optionParseBoolean(value);
else
{
2021-04-03 11:39:59 +02:00
fprintf(stderr, "Error: unknown option: %s\n", key);
2021-03-05 23:00:28 +01:00
exit(400);
}
}
2021-04-25 11:48:25 +02:00
static void parseDefaultConfigFile(FFinstance* instance, FFdata* data)
{
2021-05-07 14:55:43 +02:00
FFstrbuf* filename = ffListGet(&instance->state.configDirs, 0);
uint32_t filenameLength = filename->length;
2021-05-15 08:39:20 +02:00
mkdir(filename->chars, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a config folder, but who knows
2021-03-27 18:14:19 +01:00
2021-05-07 14:55:43 +02:00
ffStrbufAppendS(filename, "/fastfetch/");
mkdir(filename->chars, S_IRWXU | S_IRGRP | S_IROTH);
2021-05-07 14:55:43 +02:00
ffStrbufAppendS(filename, "config.conf");
2021-05-07 14:55:43 +02:00
if(access(filename->chars, F_OK) != 0)
{
2021-05-07 14:55:43 +02:00
FILE* file = fopen(filename->chars, "w");
if(file != NULL)
2021-04-25 11:48:25 +02:00
{
2021-10-22 21:53:29 +02:00
fputs(FASTFETCH_DATATEXT_CONFIG, file);
2021-05-07 14:55:43 +02:00
fclose(file);
2021-04-25 11:48:25 +02:00
}
}
2021-04-25 11:48:25 +02:00
else
2021-03-27 14:22:08 +01:00
{
2021-05-07 14:55:43 +02:00
FILE* file = fopen(filename->chars, "r");
if(file != NULL)
2021-03-28 20:09:29 +02:00
{
2021-05-07 14:55:43 +02:00
parseConfigFile(instance, data, file);
fclose(file);
}
2021-02-27 20:31:54 +01:00
}
2021-05-07 14:55:43 +02:00
ffStrbufSubstrBefore(filename, filenameLength);
}
static void parseArguments(FFinstance* instance, FFdata* data, int argc, const char** argv)
{
for(int i = 1; i < argc; i++)
{
2021-06-13 14:23:35 +02:00
if(i == argc - 1 || (*argv[i + 1] == '-' && strcasecmp(argv[i], "--offsetx") != 0)) // --offsetx allows negative values
{
parseOption(instance, data, argv[i], NULL);
}
else
{
parseOption(instance, data, argv[i], argv[i + 1]);
++i;
}
}
2021-02-27 20:31:54 +01:00
}
static void applyData(FFinstance* instance, FFdata* data)
{
//We must do this after parsing all options because of color options
2021-03-23 19:48:52 +01:00
if(data->logoName.length == 0)
ffLoadLogo(instance);
else
2021-06-13 14:23:35 +02:00
ffLoadLogoSet(instance, data->logoName.chars);
//This must be done after loading the logo
2021-03-23 19:48:52 +01:00
if(instance->config.color.length == 0)
2021-06-13 14:23:35 +02:00
ffStrbufSetS(&instance->config.color, instance->config.logo.colors[0]);
2021-03-19 20:57:07 +01:00
}
static void parseStructureCommand(FFinstance* instance, FFdata* data, const char* line)
{
const char* setValue = ffValuestoreGet(&data->valuestore, line);
if(setValue != NULL)
{
ffPrintCustom(instance, line, setValue);
return;
}
if(strcasecmp(line, "break") == 0)
ffPrintBreak(instance);
else if(strcasecmp(line, "title") == 0)
ffPrintTitle(instance);
2021-05-15 12:36:25 +02:00
else if(strcasecmp(line, "separator") == 0)
ffPrintSeparator(instance);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(line, "os") == 0)
ffPrintOS(instance);
else if(strcasecmp(line, "host") == 0)
ffPrintHost(instance);
else if(strcasecmp(line, "kernel") == 0)
ffPrintKernel(instance);
else if(strcasecmp(line, "uptime") == 0)
ffPrintUptime(instance);
2021-10-18 22:38:00 +08:00
else if(strcasecmp(line, "processes") == 0)
ffPrintProcesses(instance);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(line, "packages") == 0)
ffPrintPackages(instance);
else if(strcasecmp(line, "shell") == 0)
ffPrintShell(instance);
else if(strcasecmp(line, "resolution") == 0)
ffPrintResolution(instance);
else if(strcasecmp(line, "desktopenvironment") == 0 || strcasecmp(line, "de") == 0)
ffPrintDesktopEnvironment(instance);
else if(strcasecmp(line, "windowmanager") == 0 || strcasecmp(line, "wm") == 0)
ffPrintWM(instance);
else if(strcasecmp(line, "theme") == 0)
ffPrintTheme(instance);
2021-04-03 23:10:14 +02:00
else if(strcasecmp(line, "wmtheme") == 0)
ffPrintWMTheme(instance);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(line, "icons") == 0)
ffPrintIcons(instance);
else if(strcasecmp(line, "font") == 0)
ffPrintFont(instance);
2021-06-20 21:04:55 +02:00
else if(strcasecmp(line, "cursor") == 0)
ffPrintCursor(instance);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(line, "terminal") == 0)
ffPrintTerminal(instance);
else if(strcasecmp(line, "terminalfont") == 0)
ffPrintTerminalFont(instance);
else if(strcasecmp(line, "cpu") == 0)
ffPrintCPU(instance);
else if(strcasecmp(line, "gpu") == 0)
ffPrintGPU(instance);
else if(strcasecmp(line, "memory") == 0)
ffPrintMemory(instance);
else if(strcasecmp(line, "disk") == 0)
ffPrintDisk(instance);
else if(strcasecmp(line, "battery") == 0)
ffPrintBattery(instance);
else if(strcasecmp(line, "locale") == 0)
ffPrintLocale(instance);
2021-10-17 12:42:15 +08:00
else if(strcasecmp(line, "localip") == 0)
ffPrintLocalIp(instance);
2021-03-19 20:57:07 +01:00
else if(strcasecmp(line, "colors") == 0)
ffPrintColors(instance);
else
2021-04-15 18:59:26 +02:00
ffPrintError(instance, line, 0, NULL, NULL, 0, "<no implementation provided>");
}
static void run(FFinstance* instance, FFdata* data)
{
2021-04-07 17:36:03 +02:00
if(data->multithreading)
ffStartDetectionThreads(instance);
2021-04-07 17:36:03 +02:00
2021-03-23 19:48:52 +01:00
if(data->structure.length == 0)
2021-10-23 14:59:11 +02:00
ffStrbufSetS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
2021-03-27 18:14:19 +01:00
2021-06-17 13:49:25 +02:00
ffStart(instance);
2021-06-26 15:34:01 +02:00
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
{
2021-06-26 15:34:01 +02:00
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
2021-03-28 20:09:29 +02:00
data->structure.chars[colonIndex] = '\0';
2021-03-27 18:14:19 +01:00
2021-06-26 15:34:01 +02:00
parseStructureCommand(instance, data, data->structure.chars + startIndex);
2021-03-27 18:14:19 +01:00
2021-06-26 15:34:01 +02:00
startIndex = colonIndex + 1;
}
2021-04-07 17:36:03 +02:00
ffFinish(instance);
}
static void initData(FFdata* data)
{
ffValuestoreInit(&data->valuestore);
ffStrbufInitA(&data->structure, 256);
ffStrbufInit(&data->logoName);
data->multithreading = true;
}
int main(int argc, const char** argv)
2021-02-22 13:45:14 +01:00
{
2021-02-27 18:30:05 +01:00
FFinstance instance;
2021-04-09 14:07:05 +02:00
ffInitInstance(&instance);
FFdata data;
2021-04-07 17:36:03 +02:00
initData(&data);
2021-04-25 11:48:25 +02:00
parseDefaultConfigFile(&instance, &data);
parseArguments(&instance, &data, argc, argv);
2021-03-05 23:26:05 +01:00
applyData(&instance, &data); //Here we do things that need to be done after parsing all options
run(&instance, &data);
2021-02-18 22:25:36 +01:00
}