Files
fastfetch/src/fastfetch.c
T

1136 lines
43 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-20 21:04:55 +02:00
#define FASTFETCH_DEFAULT_STRUCTURE "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors"
#define FASTFETCH_DEFAULT_CONFIG \
2021-03-19 20:57:07 +01:00
"# Fastfetch configuration\n" \
2021-06-13 17:44:34 +05:30
"# Write every argument in different lines.\n" \
"# Direct arguments will overwrite the corresponding ones in this file.\n" \
"# Whitespaces are trimmed at the beginning and the end.\n" \
2021-03-19 20:57:07 +01:00
"# Empty lines or lines starting with # are ignored.\n" \
2021-06-13 17:44:34 +05:30
"# There are more arguments possible than the ones listed here, take a look at fastfetch --help\n" \
"# This file was shipped with "FASTFETCH_PROJECT_VERSION".\n" \
2021-03-19 20:57:07 +01:00
"# Use fastfetch --print-default-config > ~/.config/fastfetch/config.conf to generate a new one with current defaults.\n"
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-11 19:40:46 +01:00
static inline void printHelp()
2021-02-19 16:23:41 +01:00
{
puts(
2021-03-03 21:03:12 +01:00
"Usage: fastfetch <options>\n"
2021-02-20 19:32:57 +01:00
"\n"
2021-03-03 21:03:12 +01:00
"Informative options:\n"
2021-03-27 19:26:58 +01:00
" -h, --help: shows this message and exits\n"
" -h <command>, --help <command>: shows help for a specific command and exits\n"
" -v --version: prints the version of fastfetch and exits\n"
" --list-logos: list available logos and exits\n"
" --print-logos: shows available logos and exits\n"
" --print-default-config: prints the default config and exits\n"
" --print-default-structure: prints the default stucture and exits\n"
" --print-available-modules: prints a list of available modules and exits\n"
2021-04-25 11:48:25 +02:00
" --print-available-presets: list presets fastfetch knows about. They can be loaded with --load-config. (+)\n"
2021-03-03 21:03:12 +01:00
"\n"
"General options:\n"
2021-05-15 08:39:20 +02:00
" --structure <structure>: sets the structure of the fetch. Must be a colon separated list of keys. Use --print-available-modules to show the default\n"
" --set <key=value>: hard set the value of a key\n"
2021-05-09 21:41:17 +02:00
" -c <color>, --color <color>: sets the color of the keys. Must be a linux console color code (+)\n"
" --spacing <width>: sets the distance between logo and text\n"
2021-05-15 12:36:25 +02:00
" -s <str>, --separator <str>: sets the separator between key and value. Default is a colon with a space\n"
2021-05-09 21:41:17 +02:00
" -x <offset>, --offsetx <offset>: sets the x offset. Can be negative to cut the logo, but no more than logo width.\n"
" --show-errors <?value>: print occuring errors\n"
" -r <?value> --recache <?value>: generate new cached values\n"
2021-05-15 08:39:20 +02:00
" --nocache <?value>: don't use cached values, but also don't overwrite existing ones\n"
2021-05-09 21:41:17 +02:00
" --print-remaining-logo <?value>: print the remaining logo, if it is higher than the number of lines shown\n"
" --multithreading <?value>: use multiple threads to detect values\n"
" --load-config <file>: load a config file (+)\n"
" --allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output\n"
2021-06-17 13:49:25 +02:00
" --disable-linewrap <?value>: Disable linewrap during the run\n"
" --hide-cursor <?value>: Hide the cursor during the run\n"
"\n"
2021-03-03 21:03:12 +01:00
"Logo options:\n"
2021-06-13 14:23:35 +02:00
" -l <name>, --logo <name>: sets the shown logo. Also changes the main color accordingly. This will also load file contents as logo if the given argument is a path\n"
2021-03-05 23:00:28 +01:00
" --color-logo <?value>: if set to false, the logo will be black / white\n"
2021-03-03 21:03:12 +01:00
"\n"
2021-05-16 15:10:15 +02:00
"Format options: Provide the format string for custom output. Use fastfetch --help *-format for specific help.\n"
2021-03-19 20:57:07 +01:00
" --os-format <format>\n"
" --host-format <format>\n"
" --kernel-format <format>\n"
" --uptime-format <format>\n"
" --packages-format <format>\n"
" --shell-format <format>\n"
" --resolution-format <format>\n"
" --de-format <format>\n"
" --wm-format <format>\n"
2021-04-03 23:10:14 +02:00
" --wm-theme-format <format>\n"
2021-03-19 20:57:07 +01:00
" --theme-format <format>\n"
" --icons-format <format>\n"
" --font-format <format>\n"
2021-06-20 21:04:55 +02:00
" --cursor-format <format>\n"
2021-03-19 20:57:07 +01:00
" --terminal-format <format>\n"
" --terminal-font-format <format>\n"
" --cpu-format <format>\n"
" --gpu-format <format>\n"
" --memory-format <format>\n"
" --disk-format <format>\n"
" --battery-format <format>\n"
" --locale-format <format>\n"
2021-10-17 12:42:15 +08:00
" --local-ip-format <format>\n"
2021-03-06 11:28:38 +01:00
"\n"
2021-04-03 11:39:59 +02:00
"Key options: Provide a custom key for an output\n"
" --os-key <key>\n"
" --host-key <key>\n"
" --kernel-key <key>\n"
2021-04-03 23:10:14 +02:00
" --uptime-key <key>\n"
" --packages-key <key>\n"
" --shell-key <key>\n"
" --resolution-key <key>: takes the resolution index as argument\n"
2021-04-03 23:10:14 +02:00
" --de-key <key>\n"
" --wm-key <key>\n"
" --wm-theme-key <key>\n"
" --theme-key <key>\n"
" --icons-key <key>\n"
" --font-key <key>\n"
2021-06-20 21:04:55 +02:00
" --cursor-key <key>\n"
2021-04-03 23:10:14 +02:00
" --terminal-key <key>\n"
" --terminal-font-key <key>\n"
" --cpu-key <key>\n"
" --gpu-key <key>: takes the gpu index as format argument\n"
" --memory-key <key>\n"
" --disk-key <key>: takes the mount path as format argument\n"
" --battery-key <key>: takes the battery index as format argument\n"
" --locale-key <key>\n"
2021-10-17 12:42:15 +08:00
" --local-ip-key <key>: takes the name of this network interface as format argument\n"
2021-04-03 11:39:59 +02:00
"\n"
2021-03-19 20:57:07 +01:00
"Library optins: Set the path of a library to load\n"
" --lib-PCI <path>\n"
2021-03-21 11:18:06 +01:00
" --lib-X11 <path>\n"
" --lib-Xrandr <path>\n"
2021-05-02 18:52:42 +02:00
" --lib-gio <path>\n"
2021-04-05 23:42:07 +02:00
" --lib-DConf <path>\n"
2021-04-16 16:49:33 +02:00
" --lib-wayland <path>\n"
2021-05-11 20:06:17 +02:00
" --lib-XFConf <path>\n"
2021-06-08 20:01:29 +02:00
" --lib-SQLite <path>\n"
2021-04-03 11:39:59 +02:00
"\n"
2021-03-28 15:38:52 +02:00
"Module specific options:\n"
2021-10-17 12:42:15 +08:00
" --disk-folders <folders>: A colon separated list of folder paths for the disk output. Default is \"/:/home\"\n"
" --battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/\n"
" --localip-show-ipv4 <?value>: Show ipv4 addresses in local ip module. Default is true\n"
" --localip-show-ipv6 <?value>: Show ipv6 addresses in local ip module. Default is false\n"
" --localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false\n"
2021-03-03 21:03:12 +01:00
"\n"
2021-04-28 19:45:43 +02:00
"Parsing is not case sensitive. E.g. \"--lib-PCI\" is equal to \"--Lib-Pci\"\n"
"If a value starts with a ?, it is optional. \"true\" will be used if not set.\n"
"A (+) at the end indicates that more help can be printed with --help <option>\n"
2021-05-15 08:39:20 +02:00
"All options can be made permanent in $XDG_CONFIG_HOME/fastfetch/config.conf"
2021-02-19 16:23:41 +01:00
);
}
2021-03-04 20:49:12 +01:00
static inline void printCommandHelpColor()
2021-02-20 19:32:57 +01:00
{
puts(
"usage: fastfetch --color <color>\n"
"\n"
"<color> must be a color encoding for linux terminals. It is inserted between \"ESC[\" and \"m\".\n"
2021-04-25 09:13:18 +02:00
"Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.\n"
2021-02-20 19:32:57 +01:00
"Examples:\n"
" \"--color 35\": sets the color to pink\n"
" \"--color 4;92\": sets the color to bright Green with underline\n"
" \"--color 5;104\": blinking text on a blue background\n"
2021-02-20 20:00:06 +01:00
"If no color is set, the main color of the logo will be used.\n"
2021-02-20 19:32:57 +01:00
);
}
2021-03-21 11:18:06 +01:00
static inline void printCommandHelpFormat()
2021-03-12 10:17:49 +01:00
{
puts(
2021-05-15 08:39:20 +02:00
"A format string is a string that contains placeholders for values.\n"
"These placeholders begin with a '{', containing the index of the value, and end with a '}'.\n"
2021-03-21 11:18:06 +01:00
"For example the format string \"Values: {1} ({2})\", with the values \"First\" and \"My second val\", will produce \"Values: First (My second val)\".\n"
2021-05-15 08:39:20 +02:00
"The format string can contain placeholders in any order and have multiple occurences.\n"
"To include spaces when setting from the command line, surround the whole string with double quotes (\").\n"
2021-03-21 11:18:06 +01:00
"\n"
"If the value index is missing, meaning the placeholder is \"{}\", an internal counter sets the value index.\n"
2021-05-15 08:39:20 +02:00
"This means that the format string \"Values: {1} ({2})\" is equivalent to \"Values: {} ({})\".\n"
"Note that this counter only counts empty placeholders, so the format string \"{2} {} {}\" will contain the second value, then the first, and then the second again.\n"
2021-03-21 11:18:06 +01:00
"\n"
2021-05-15 08:39:20 +02:00
"To make formatting easier, a double open curly brace (\"{{\") will be printed as a single open curly brace and not counted as the beginning of a placeholder.\n"
"If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces around it.\n"
2021-04-24 21:42:48 +02:00
"If the last placeholder isn't closed, it will be treated like it was at the end of the format string.\n"
"\n"
2021-05-15 08:39:20 +02:00
"To only print something if a variable is set, use \"{?<index>} ... {?}\".\n"
"For example, to only print a second value if it is set, use \"{?2} Second value: {2}{?}\".\n"
2021-04-24 21:42:48 +02:00
"If a \"{?}\" is found without an opener, it is printed as is.\n"
"\n"
"To only print something if a variable is not set, do the same as with if, just replace every '?' with a '!'.\n"
2021-05-15 08:39:20 +02:00
"For example to print a fallback for a second value if it is not set, use \"{?2}{2}{?}{/2}Second value fallback{/}\".\n"
2021-04-24 21:42:48 +02:00
"\n"
2021-05-15 08:39:20 +02:00
"There is a special variable set if an error occured during detection. You can access it with \"{e}\", \"{error}\" or \"{0}\".\n"
"You can use ifs and not ifs with it like with an index. For example use \"{?e}some text{?}\", to print a text if an error occurred.\n"
2021-04-24 21:42:48 +02:00
"\n"
2021-05-15 08:39:20 +02:00
"To stop formatting at any point in the format string, use \"{-}\".\n"
2021-04-24 21:42:48 +02:00
"For example to print an error instead of the normal output if it occured, prefix the format string with \"{?e}{e}{-}{?}...\".\n"
2021-03-21 11:18:06 +01:00
"\n"
2021-04-25 09:13:18 +02:00
"To print something with color, start a placeholder with a '#' and then the linux terminal color encoding.\n"
2021-05-15 08:39:20 +02:00
"\"\\033[\" at the start, and an 'm' at the end is automatically added, so don't do that.\n"
2021-04-25 09:13:18 +02:00
"A \"{#}\" is equivalent to a \"{#0}\" and resets everything to normal.\n"
2021-05-15 08:39:20 +02:00
"For example to print something pink and underline, use \"{#4;35}...{#}\".\n"
2021-04-25 09:13:18 +02:00
"If not in a format string, fastfetch wraps errors with \"{#1;31}error{#}\", so you might want to do that to if you show errors.\n"
"Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.\n"
2021-05-15 08:39:20 +02:00
"Which escape codes are supported and how they look is defined by your terminal.\n"
2021-04-25 09:13:18 +02:00
"\n"
2021-05-15 08:39:20 +02:00
"If a format string evaluates to an empty value, the whole line in the output will be discarded.\n"
"You can therefore use --host-format \" \" to disable host output.\n"
2021-05-15 08:39:20 +02:00
"Note that --host-format \"\" would evaluate as not set, and therefore use the built-in host format\n"
2021-04-24 21:42:48 +02:00
"This can be used to print nothing if an error occured: prefix the format string with \"{?e}{-}{?}...\".\n"
"\n"
2021-05-15 08:39:20 +02:00
"Format string is also the way to go to set a fixed value - just use one without placeholders.\n"
"For example when running in headless mode, you could use \"--resolution-format \"Preferred\"."
2021-03-19 20:57:07 +01:00
);
}
2021-04-25 11:48:25 +02:00
static inline void printCommandHelpLoadConfig()
2021-03-27 19:26:58 +01:00
{
puts(
2021-04-25 11:48:25 +02:00
"usage: fastfetch --load-config <file>\n"
2021-03-27 19:26:58 +01:00
"\n"
2021-04-25 11:48:25 +02:00
"Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.\n"
"If the file is relative it looks in the following order:\n"
" - relative to the current working directory\n"
" - relative to ~/.local/share/fastfetch/presets/\n"
" - relative to /usr/share/fastfetch/presets/\n"
"Fastfetch provides some default presets. List them with --print-available-presets.\n"
"Note that this will only print presets fastfetch knows about and not every possible one."
2021-03-27 19:26:58 +01:00
);
}
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-03-04 20:49:12 +01:00
if(strcasecmp(command, "c") == 0 || strcasecmp(command, "color") == 0)
2021-02-20 19:32:57 +01:00
printCommandHelpColor();
2021-03-21 11:18:06 +01:00
else if(strcasecmp(command, "format") == 0)
printCommandHelpFormat();
2021-04-25 11:48:25 +02:00
else if(strcasecmp(command, "load-config") == 0)
printCommandHelpLoadConfig();
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-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 printAvailableModules()
{
puts(
"Battery\n"
"Break\n"
"Colors\n"
"CPU\n"
2021-06-20 21:04:55 +02:00
"Cursor\n"
2021-04-25 11:48:25 +02:00
"DE\n"
"Disk\n"
"Font\n"
"GPU\n"
"Host\n"
"Icons\n"
"Kernel\n"
"Locale\n"
2021-10-17 12:42:15 +08:00
"LocalIp\n"
2021-04-25 11:48:25 +02:00
"Memory\n"
"OS\n"
"Packages\n"
"Resolution\n"
2021-05-15 12:36:25 +02:00
"Separator\n"
2021-04-25 11:48:25 +02:00
"Shell\n"
"Terminal\n"
"TerminalFont\n"
"Theme\n"
"Title\n"
"Uptime\n"
"WM\n"
"WMTheme\n"
"\n"
"+ Additional defined by --set"
);
}
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 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);
ffStrbufDestroy(&line);
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)
{
if(value == NULL)
printHelp();
else
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);
}
else if(strcasecmp(key, "--print-default-config") == 0)
{
puts(FASTFETCH_DEFAULT_CONFIG);
exit(0);
}
2021-03-27 19:26:58 +01:00
else if(strcasecmp(key, "--print-default-structure") == 0)
{
puts(FASTFETCH_DEFAULT_STRUCTURE);
exit(0);
}
else if(strcasecmp(key, "--print-available-modules") == 0)
{
printAvailableModules();
exit(0);
}
2021-04-25 11:48:25 +02:00
else if(strcasecmp(key, "--print-available-presets") == 0)
{
listAvailablePresets(instance);
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-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-05-07 14:55:43 +02:00
fputs(FASTFETCH_DEFAULT_CONFIG, file);
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);
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-03-19 20:57:07 +01:00
ffStrbufSetS(&data->structure, FASTFETCH_DEFAULT_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
}