Compare commits

..

42 Commits

Author SHA1 Message Date
Carter Li c151bf0b37 Merge pull request #695 from fastfetch-cli/dev
Release v2.6.2
2024-01-21 17:54:12 +08:00
李通洲 a767104b96 TerminalShell (Windows): more variable initialization fixes 2024-01-21 17:52:03 +08:00
Carter Li 18fced9b2e Merge pull request #694 from fastfetch-cli/dev
Release 2.6.2
2024-01-21 17:46:02 +08:00
李通洲 713ef0ce34 Release: v2.6.2 2024-01-21 17:41:34 +08:00
李通洲 5b2db02bc1 CI: Fix building for GCC in Windows 2024-01-21 17:39:31 +08:00
Carter Li 0f69dc5980 Merge pull request #692 from fastfetch-cli/dev
Release 2.6.1
2024-01-20 22:34:06 +08:00
李通洲 6af57ff5b6 Doc: update changelog 2024-01-20 22:20:28 +08:00
Carter Li 7d7789565b PowerAdapter (macOS): improve detection for Intel macbook 2024-01-20 21:46:57 +08:00
Carter Li 0eb76e9636 Battery (macOS): improve manufacture info detection 2024-01-20 21:38:24 +08:00
李通洲 8b1ee64a3e GPU (macOS): fix gpu type detection 2024-01-20 20:57:33 +08:00
李通洲 b0acf168bf Doc: update changelog 2024-01-20 20:14:56 +08:00
李通洲 7ddc207574 Percentage: add options --percent-color-* 2024-01-20 20:06:42 +08:00
李通洲 d1a791b333 Global: make threshold of percentage colors configurable
Fix #689
2024-01-20 18:40:12 +08:00
李通洲 62ca495155 Percentage: prepare to make threshold configurable 2024-01-20 14:10:56 +08:00
李通洲 e7974a7cea Percentage: refactor function names 2024-01-20 13:49:04 +08:00
李通洲 24cb83dd18 Bluetooth / Gamepad / Sound: support percentage number formatting 2024-01-20 13:48:42 +08:00
李通洲 da5c44b3d0 Percentage: simplify usage of ffAppendPercentBar 2024-01-20 13:27:55 +08:00
李通洲 bd71aa931f Global: rename common/bar to common/percent 2024-01-20 11:28:38 +08:00
李通洲 4d1f242e1d Terminal (Windows): tidy 2024-01-19 22:23:32 +08:00
李通洲 d810245d55 Doc: update changelog 2024-01-19 21:54:44 +08:00
李通洲 06181ec433 Terminal (Windows): default default terminal to conhost 2024-01-19 21:54:44 +08:00
李通洲 8404ae034f Locale: improve detection
Linux: always use `setlocale`, fix #688
Windows: don't append `UTF-8`
2024-01-19 21:15:05 +08:00
李通洲 8e7d465333 Fastfetch: create sub folders when writing config file
Fix #690
2024-01-19 21:01:02 +08:00
李通洲 87813b3306 Shell: detect associated TTY 2024-01-19 16:43:08 +08:00
李通洲 9610a1ab23 TerminalShell (Windows): simplify nested shell detection by looking up GUI objects 2024-01-19 15:00:10 +08:00
李通洲 5f14781970 TerminalShell (Windows): set exePath 2024-01-19 14:40:07 +08:00
Carter Li 356488be0c TerminalShell (FreeBSD): detect real exe path 2024-01-19 14:40:07 +08:00
Carter Li e013c87890 TerminalShell (Linux): detect real exe path 2024-01-19 14:40:07 +08:00
李通洲 7d78d92a92 TerminalShell (macOS): detect full exe path 2024-01-19 14:40:07 +08:00
李通洲 06af39835a Terminal: don't use login as terminal process; set ppid 2024-01-19 14:40:07 +08:00
Carter Li eee8fb78d2 Shell (FreeBSD): detect arg0 instead of exe path 2024-01-19 14:40:07 +08:00
Carter Li 413f91260d Processes (FreeBSD): don't count sub-threads as processes 2024-01-19 14:40:07 +08:00
李通洲 a44daa04d6 Shell (Windows): better support xonsh detection 2024-01-18 18:08:08 +08:00
李通洲 d6cb405afe Release: v2.6.1 2024-01-18 15:31:36 +08:00
李通洲 b2a853cb6e Doc: update changelog 2024-01-18 15:28:49 +08:00
李通洲 0168f2e9a8 Shell: improve xonsh version detection 2024-01-18 15:27:31 +08:00
李通洲 3992d85eb6 CPU (Linux): show vendor if no model name available 2024-01-18 15:16:46 +08:00
李通洲 5096180e92 CPU (Linux): don't access out-of-bound memory 2024-01-18 15:06:47 +08:00
李通洲 947d2ff0a9 Processing (Linux): return error when command is not found 2024-01-18 14:54:14 +08:00
李通洲 1e4f174415 Shell (macOS): improve handling of xonsh 2024-01-18 14:07:29 +08:00
李通洲 2808b1a653 TerminalShell: improve xonsh version detection 2024-01-17 23:45:39 +08:00
李通洲 c749f214e0 Global: silence warnings when building in 32bit environments 2024-01-17 23:12:55 +08:00
53 changed files with 1015 additions and 404 deletions
+24
View File
@@ -1,3 +1,27 @@
# 2.6.2
Bugfixes:
* Fix building for GCC in Windows (Windows)
# 2.6.1
Features:
* Improve xonsh shell detection (Shell)
* Support colored percentage values (Bluetooth / Gamepad / Sound)
* Add `--<module>-percent-[green|yellow]` options to specify threshold of percentage colors
* eg. `--disk-percent-green 20 --disk-percent-yellow 50` will show green if disk usage is less than 20%, yellow if disk usage is less then 50%, and red otherwise.
* Add `--percent-color-[green|yellow|red]` options to specify color of different percent value states.
* eg. `--percent-color-green blue` will show blue color if percent value falls in green state.
* Improve Intel macbook support (macOS)
Bugfixes:
* Fix segfault in CPU module when running in aarch64 machine without `lscpu` installed (CPU, Linux)
* Don't use `login` as terminal process (Terminal, Linux)
* Silence warnings when building in 32bit machines.
* Create sub folders when writing config file (#690)
* Improve user specific locale detection; fix locale detection in Windows 7 (Locale)
* Fix GPU type detection (GPU, macOS)
# 2.6.0
Changes:
+2 -2
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.6.0
VERSION 2.6.2
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -265,7 +265,7 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
#######################
set(LIBFASTFETCH_SRC
src/common/bar.c
src/common/percent.c
src/common/commandoption.c
src/common/font.c
src/common/format.c
+129 -12
View File
@@ -26,6 +26,24 @@
"format": {
"description": "Output format of the module",
"type": "string"
},
"percent": {
"description": "Threshold of percentage colors",
"type": "object",
"properties": {
"green": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Value less then green will be shown in green"
},
"yellow": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Value greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red"
}
}
}
},
"type": "object",
@@ -439,6 +457,24 @@
"minimum": 0,
"maximum": 9,
"default": 0
},
"color": {
"type": "object",
"description": "Set color used in different states of percentage bars and numbers",
"properties": {
"green": {
"description": "Color used in green state",
"$ref": "#/$defs/colors"
},
"yellow": {
"description": "Color used in yellow state",
"$ref": "#/$defs/colors"
},
"red": {
"description": "Color used in red state",
"$ref": "#/$defs/colors"
}
}
}
}
},
@@ -672,10 +708,6 @@
"const": "font",
"description": "Print system font name"
},
{
"const": "gamepad",
"description": "List connected gamepads"
},
{
"const": "host",
"description": "Print product name of your computer"
@@ -700,10 +732,6 @@
"const": "media",
"description": "Print playing song name"
},
{
"const": "memory",
"description": "Print system memory usage info"
},
{
"const": "monitor",
"description": "Print connected physical monitor information"
@@ -732,10 +760,6 @@
"const": "shell",
"description": "Print current shell name and version"
},
{
"const": "swap",
"description": "Print swap (paging file) space usage"
},
{
"const": "terminal",
"description": "Print current terminal name and version"
@@ -814,6 +838,9 @@
"type": "boolean",
"default": false
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -841,6 +868,9 @@
"type": "boolean",
"default": false
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -863,6 +893,9 @@
"const": "brightness",
"description": "Print current brightness level of your monitors"
},
"percent": {
"$ref": "#/$defs/percent"
},
"ddcciSleep": {
"type": "integer",
"description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail",
@@ -934,6 +967,9 @@
"const": "cpuusage",
"description": "Print CPU usage. Costs some time to collect data"
},
"percent": {
"$ref": "#/$defs/percent"
},
"separate": {
"type": "boolean",
"description": "Display CPU usage per CPU logical core, instead of an average result",
@@ -1103,6 +1139,9 @@
"description": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes",
"default": false
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1170,6 +1209,31 @@
}
}
},
{
"title": "Gamepad",
"properties": {
"type": {
"const": "gamepad",
"description": "List connected gamepads"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
},
{
"title": "GPU",
"properties": {
@@ -1272,6 +1336,31 @@
},
"additionalProperties": false
},
{
"title": "Memory",
"properties": {
"type": {
"const": "memory",
"description": "Print system memory usage info"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
},
{
"title": "NetIO",
"properties": {
@@ -1458,6 +1547,34 @@
],
"default": "main"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
},
{
"title": "Swap",
"properties": {
"type": {
"const": "swap",
"description": "Print swap (paging file) space usage"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
-111
View File
@@ -1,111 +0,0 @@
#include "common/bar.h"
#include "common/color.h"
#include "util/textModifier.h"
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red)
{
assert(green <= 100 && yellow <= 100 && red <= 100);
const FFOptionsDisplay* options = &instance.config.display;
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
uint32_t blocksGreen = (uint32_t) (green / 100.0 * options->barWidth + 0.5);
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * options->barWidth + 0.5);
uint32_t blocksRed = (uint32_t) (red / 100.0 * options->barWidth + 0.5);
assert(blocksPercent <= options->barWidth);
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
else
ffStrbufAppendS(buffer, "[ ");
}
for (uint32_t i = 0; i < blocksPercent; ++i)
{
if(!options->pipe)
{
if (i == blocksGreen)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
else if (i == blocksYellow)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
else if (i == blocksRed)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
ffStrbufAppend(buffer, &options->barCharElapsed);
}
if (blocksPercent < options->barWidth)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharTotal);
}
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
else
ffStrbufAppendS(buffer, " ]");
}
if(!options->pipe)
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
// if (green < yellow)
// [0, green]: print green
// (green, yellow]: print yellow
// (yellow, 100]: print red
//
// if (green > yellow)
// [green, 100]: print green
// [yellow, green): print yellow
// [0, yellow): PRINT RED
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses)
{
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
if (colored && !options->pipe)
{
if(percent != percent)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
else if(green < yellow)
{
if (percent <= green)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
else if (percent <= yellow)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
else
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
else
{
if (percent >= green)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
else if (percent >= yellow)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
else
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
}
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
if (colored && !options->pipe)
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
if (parentheses)
ffStrbufAppendC(buffer, ')');
}
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#include "fastfetch.h"
enum
{
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
};
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red);
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses);
+1 -1
View File
@@ -57,7 +57,7 @@ static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
uint32_t result = UINT32_MAX;
if(placeholderValue->chars[0] != '-')
sscanf(placeholderValue->chars, "%u", &result);
sscanf(placeholderValue->chars, "%" PRIu32, &result);
return result == 0 ? UINT32_MAX : result;
}
+1 -1
View File
@@ -143,7 +143,7 @@ void ffOptionParseColor(const char* value, FFstrbuf* buffer)
while(*value != '\0')
{
#define FF_APPEND_COLOR_CODE_COND(prefix, code) \
if(strncasecmp(value, #prefix, strlen(#prefix)) == 0) { ffStrbufAppendS(buffer, code); value += strlen(#prefix); }
if(ffStrStartsWithIgnCase(value, #prefix)) { ffStrbufAppendS(buffer, code); value += strlen(#prefix); }
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
+211
View File
@@ -0,0 +1,211 @@
#include "fastfetch.h"
#include "common/percent.h"
#include "common/color.h"
#include "common/option.h"
#include "common/jsonconfig.h"
#include "util/textModifier.h"
#include "util/stringUtils.h"
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config)
{
uint8_t green = config.green, yellow = config.yellow;
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
assert(blocksPercent <= options->barWidth);
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
else
ffStrbufAppendS(buffer, "[ ");
}
if (percent != percent)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
for (uint32_t i = 0; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharElapsed);
}
else
{
const char* colorGreen = instance.config.display.percentColorGreen.chars;
const char* colorYellow = instance.config.display.percentColorYellow.chars;
const char* colorRed = instance.config.display.percentColorRed.chars;
for (uint32_t i = 0; i < blocksPercent; ++i)
{
if(!options->pipe)
{
uint32_t section1Begin = (uint32_t) ((green <= yellow ? green : yellow) / 100.0 * options->barWidth + 0.5);
uint32_t section2Begin = (uint32_t) ((green > yellow ? green : yellow) / 100.0 * options->barWidth + 0.5);
if (i == section2Begin)
ffStrbufAppendF(buffer, "\e[%sm", (green > yellow ? colorGreen : colorRed));
else if (i == section1Begin)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else if (i == 0)
ffStrbufAppendF(buffer, "\e[%sm", (green <= yellow ? colorGreen : colorRed));
}
ffStrbufAppend(buffer, &options->barCharElapsed);
}
if (blocksPercent < options->barWidth)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharTotal);
}
}
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
else
ffStrbufAppendS(buffer, " ]");
}
if(!options->pipe)
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses)
{
uint8_t green = config.green, yellow = config.yellow;
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
if (colored && !options->pipe)
{
const char* colorGreen = instance.config.display.percentColorGreen.chars;
const char* colorYellow = instance.config.display.percentColorYellow.chars;
const char* colorRed = instance.config.display.percentColorRed.chars;
if(percent != percent)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
else if(green <= yellow)
{
if (percent > yellow)
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
else if (percent > green)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
else
{
if (percent < yellow)
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
else if (percent < green)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
}
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
if (colored && !options->pipe)
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
if (parentheses)
ffStrbufAppendC(buffer, ')');
}
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config)
{
if (!ffStrStartsWithIgnCase(subkey, "percent-"))
return false;
subkey += strlen("percent-");
if (ffStrEqualsIgnCase(subkey, "green"))
{
uint32_t num = ffOptionParseUInt32(key, value);
if (num > 100)
{
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
exit(480);
}
config->green = (uint8_t) num;
return true;
}
if (ffStrEqualsIgnCase(subkey, "yellow"))
{
uint32_t num = ffOptionParseUInt32(key, value);
if (num > 100)
{
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
exit(480);
}
config->yellow = (uint8_t) num;
return true;
}
return false;
}
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config)
{
if (!ffStrEqualsIgnCase(key, "percent"))
return false;
if (!yyjson_is_obj(value))
{
fprintf(stderr, "Error: usage: %s must be an object\n", key);
exit(480);
}
yyjson_val* greenVal = yyjson_obj_get(value, "green");
if (greenVal)
{
int num = yyjson_get_int(greenVal);
if (num < 0 || num > 100)
{
fputs("Error: usage: percent.green must be between 0 and 100\n", stderr);
exit(480);
}
config->green = (uint8_t) num;
}
yyjson_val* yellowVal = yyjson_obj_get(value, "yellow");
if (yellowVal)
{
int num = yyjson_get_int(yellowVal);
if (num < 0 || num > 100)
{
fputs("Error: usage: percent.yellow must be between 0 and 100\n", stderr);
exit(480);
}
config->yellow = (uint8_t) num;
}
return true;
}
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config)
{
if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow)
return;
yyjson_mut_val* percent = yyjson_mut_obj_add_obj(doc, module, "percent");
if (config.green != defaultConfig.green)
yyjson_mut_obj_add_uint(doc, percent, "green", config.green);
if (config.yellow != defaultConfig.yellow)
yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow);
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "util/FFstrbuf.h"
enum
{
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
};
typedef struct FFPercentConfig
{
uint8_t green;
uint8_t yellow;
} FFPercentConfig;
// if (green <= yellow)
// [0, green]: print green
// (green, yellow]: print yellow
// (yellow, 100]: print red
//
// if (green > yellow)
// [green, 100]: print green
// [yellow, green): print yellow
// [0, yellow): print red
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config);
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses);
typedef struct yyjson_val yyjson_val;
typedef struct yyjson_mut_doc yyjson_mut_doc;
typedef struct yyjson_mut_val yyjson_mut_val;
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config);
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config);
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config);
+16 -9
View File
@@ -13,13 +13,6 @@
enum { FF_PIPE_BUFSIZ = 8192 };
static inline void waitpid_wrapper(const pid_t* pid)
{
// remove zombie processes
if (*pid > 0)
waitpid(*pid, NULL, 0);
}
static inline int ffPipe2(int *fds, int flags)
{
#ifdef __APPLE__
@@ -41,7 +34,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if(ffPipe2(pipes, O_CLOEXEC) == -1)
return "pipe() failed";
__attribute__((__cleanup__(waitpid_wrapper))) pid_t childPid = fork();
pid_t childPid = fork();
if(childPid == -1)
{
close(pipes[0]);
@@ -74,11 +67,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if (poll(&pollfd, 1, timeout) == 0)
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) timeout";
}
else if (pollfd.revents & POLLERR)
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) error";
}
}
@@ -87,7 +82,19 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if (nRead > 0)
ffStrbufAppendNS(buffer, (uint32_t) nRead, str);
else if (nRead == 0)
return NULL;
{
int stat_loc = 0;
if (waitpid(childPid, &stat_loc, 0) == childPid)
{
if (!WIFEXITED(stat_loc))
return "child process exited abnormally";
if (WEXITSTATUS(stat_loc) == 127)
return "command was not found";
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
return NULL;
}
return "waitpid() failed";
}
else if (nRead < 0)
break;
};
+1 -1
View File
@@ -42,6 +42,6 @@ static inline void ffTimeSleep(uint32_t msec)
#ifdef _WIN32
SleepEx(msec, TRUE);
#else
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
nanosleep(&(struct timespec){ msec / 1000, (long) (msec % 1000) * 1000000 }, NULL);
#endif
}
+56
View File
@@ -198,6 +198,7 @@
{
"long": "logo-color-[1-9]",
"desc": "Overwrite a color in the logo",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color"
},
@@ -432,6 +433,7 @@
{
"long": "color-keys",
"desc": "Set the color of the keys",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color"
}
@@ -439,6 +441,7 @@
{
"long": "color-title",
"desc": "Set the color of the title",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color"
}
@@ -548,6 +551,33 @@
"default": 0
}
},
{
"long": "percent-color-green",
"desc": "Set color used in green state of percentage bars and numbers",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "green"
}
},
{
"long": "percent-color-yellow",
"desc": "Set color used in yellow state of percentage bars and numbers",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "light_yellow"
}
},
{
"long": "percent-color-red",
"desc": "Set color used in red state of percentage bars and numbers",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "light_red"
}
},
{
"long": "bar-char-elapsed",
"desc": "Set the character to use in elapsed part of percentage bars",
@@ -821,6 +851,7 @@
{
"long": "title-color-user",
"desc": "Set color of the user name (left part)",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "Use color of \"--color-title\""
@@ -829,6 +860,7 @@
{
"long": "title-color-at",
"desc": "Set color of the @ symbol (middle part)",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "Use color of \"--color-title\""
@@ -837,6 +869,7 @@
{
"long": "title-color-host",
"desc": "Set color of the host name (right part)",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "default"
@@ -1351,6 +1384,29 @@
"type": "num"
},
"pseudo": true
},
{
"long": "<module>-percent-green",
"desc": [
"Threshold of percentage colors",
"Value less then percent-green will be shown in green"
],
"arg": {
"type": "num"
},
"pseudo": true
},
{
"long": "<module>-percent-yellow",
"desc": [
"Threshold of percentage colors",
"Value greater than percent-green and less then yellow will be shown in yellow",
"Value greater than percent-yellow will be shown in red"
],
"arg": {
"type": "num"
},
"pseudo": true
}
]
}
+23 -10
View File
@@ -44,10 +44,12 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial);
ffCfDictGetString(properties, CFSTR(kIOPMPSManufacturerKey), &battery->manufacturer);
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
{
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
if (!battery->manufacturer.length)
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
ffStrbufAppendS(&battery->technology, "Lithium");
if (!battery->modelName.length)
ffStrbufAppendS(&battery->modelName, "Built-in");
@@ -68,17 +70,28 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
CFDictionaryRef batteryData;
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL)
int sbdsManufactureDate = 0;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSManufactureDateKey), &sbdsManufactureDate) == NULL)
{
char manufactureDate[sizeof(uint64_t)];
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL)
int day = sbdsManufactureDate & 0b11111;
int month = (sbdsManufactureDate >> 5) & 0b1111;
int year = (sbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
else
{
CFDictionaryRef batteryData;
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL)
{
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
char manufactureDate[sizeof(uint64_t)];
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL)
{
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
}
+3 -3
View File
@@ -203,9 +203,9 @@ const char* detectBySmbios(FFBatteryResult* battery)
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsManufactureDate))
{
uint16_t day = data->SbdsManufactureDate & 0b11111;
uint16_t month = (data->SbdsManufactureDate >> 5) & 0b1111;
uint16_t year = (data->SbdsManufactureDate >> 9) + 1800;
int day = data->SbdsManufactureDate & 0b11111;
int month = (data->SbdsManufactureDate >> 5) & 0b1111;
int year = (data->SbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
+8 -1
View File
@@ -191,6 +191,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffStrbufAppendS(&cpu->vendor, pstart);
}
pstart = pend + 1;
if (pstart >= buffer.chars + buffer.length)
return NULL;
}
}
}
@@ -207,7 +209,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (*pstart == '-')
{
ffStrbufAppendS(&cpu->name, "Unknown");
if (cpu->vendor.length > 0)
ffStrbufAppend(&cpu->name, &cpu->vendor);
else
ffStrbufAppendS(&cpu->name, "Unknown");
++pstart;
continue;
}
@@ -222,6 +227,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
}
pstart = pend + 1;
if (pstart >= buffer.chars + buffer.length)
return NULL;
}
}
}
+2 -1
View File
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <limits.h>
#include <inttypes.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
@@ -89,7 +90,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(sysBlockStat) - 1, sysBlockStat);
if (fileSize <= 0) continue;
sysBlockStat[fileSize] = '\0';
if (sscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) <= 0)
if (sscanf(sysBlockStat, "%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) <= 0)
continue;
}
+1 -1
View File
@@ -46,7 +46,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
continue;
}
uint32_t width = 0, height = 0;
unsigned width = 0, height = 0;
int scanned = sscanf(modes, "%ux%u", &width, &height);
if(scanned == 2 && width > 0 && height > 0)
+1 -1
View File
@@ -32,7 +32,7 @@ const char* ffGpuDetectMetal(FFlist* gpus)
else if ([device supportsFamily:MTLGPUFamilyCommon1])
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
if (gpu->type == device.hasUnifiedMemory)
if (device.hasUnifiedMemory)
{
gpu->type = FF_GPU_TYPE_INTEGRATED;
gpu->shared.total = device.recommendedMaxWorkingSetSize;
+1 -1
View File
@@ -77,7 +77,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
// See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html
// displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1"
uint32_t vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
+5 -51
View File
@@ -1,61 +1,15 @@
#include "detection/locale/locale.h"
#include "common/properties.h"
#include "common/parsing.h"
#include <stdlib.h>
#include <locale.h>
FF_MAYBE_UNUSED
static void getLocaleFromEnv(FFstrbuf* locale)
{
ffStrbufAppendS(locale, getenv("LANG"));
if(locale->length > 0)
return;
ffStrbufAppendS(locale, getenv("LC_ALL"));
if(locale->length > 0)
return;
ffStrbufAppendS(locale, getenv("LC_MESSAGES"));
}
static void getLocaleFromStdFn(FFstrbuf* locale)
{
#ifdef LC_MESSAGES
ffStrbufAppendS(locale, setlocale(LC_MESSAGES, NULL));
if(locale->length > 0)
return;
#endif
ffStrbufAppendS(locale, setlocale(LC_ALL, NULL));
}
void ffDetectLocale(FFstrbuf* result)
{
#if !(defined(__APPLE__) || defined(_WIN32))
//Ubuntu (and deriviates) use a non standard locale file.
//Parse it first, because on distributions where it exists, it takes precedence.
//Otherwise use the standard etc/locale.conf file.
ffParsePropFile(FASTFETCH_TARGET_DIR_ETC"/default/locale", "LANG =", result);
if(result->length > 0)
return;
ffParsePropFile(FASTFETCH_TARGET_DIR_ETC"/locale.conf", "LANG =", result);
if(result->length > 0)
return;
#ifdef LC_MESSAGES
ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL));
if(result->length > 0)
return;
#endif
#ifndef _WIN32
getLocaleFromEnv(result);
if(result->length > 0)
return;
#endif
getLocaleFromStdFn(result);
ffStrbufAppendS(result, setlocale(LC_ALL, NULL));
}
-5
View File
@@ -9,10 +9,5 @@ void ffDetectLocale(FFstrbuf* result)
wchar_t name[LOCALE_NAME_MAX_LENGTH];
int size = GetUserDefaultLocaleName(name, LOCALE_NAME_MAX_LENGTH);
if (size > 1) // including '\0'
{
ffStrbufSetNWS(result, (uint32_t)size - 1, name);
ffStrbufAppendS(result, ".UTF-8"); // set explicitly in `ffInitInstance`
}
else
ffStrbufSetS(result, setlocale(LC_ALL, NULL));
}
@@ -7,7 +7,6 @@
const char* ffDetectPowerAdapter(FFlist* results)
{
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
FFPowerAdapterResult* adapter = ffListAdd(results);
ffStrbufInit(&adapter->name);
@@ -17,13 +16,24 @@ const char* ffDetectPowerAdapter(FFlist* results)
ffStrbufInit(&adapter->serial);
adapter->watts = FF_POWERADAPTER_NOT_CONNECTED;
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
if (details)
{
ffCfDictGetString(details, CFSTR(kIOPSNameKey), &adapter->name);
ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName);
if (ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName) != NULL)
{
int adapterId;
if (ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterIDKey), &adapterId) == 0)
ffStrbufSetF(&adapter->modelName, "%d", adapterId);
}
ffCfDictGetString(details, CFSTR("Manufacturer"), &adapter->manufacturer);
ffCfDictGetString(details, CFSTR("Description"), &adapter->description);
ffCfDictGetString(details, CFSTR("SerialString"), &adapter->serial);
if (ffCfDictGetString(details, CFSTR("SerialString"), &adapter->serial) != NULL)
{
int serialNumber;
if (ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterSerialNumberKey), &serialNumber) == 0)
ffStrbufSetF(&adapter->serial, "%X", serialNumber);
}
ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterWattsKey), &adapter->watts);
}
+6 -2
View File
@@ -6,13 +6,17 @@
#include <sys/user.h>
#endif
#ifndef KERN_PROC_PROC
#define KERN_PROC_PROC KERN_PROC_ALL // Apple
#endif
const char* ffDetectProcesses(uint32_t* result)
{
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
size_t length;
if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0)
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed";
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed";
*result = (uint32_t)(length / sizeof(struct kinfo_proc));
return NULL;
+19 -5
View File
@@ -168,6 +168,23 @@ static bool getShellVersionAsh(FFstrbuf* exe, FFstrbuf* version)
return true;
}
static bool getShellVersionXonsh(FFstrbuf* exe, FFstrbuf* version)
{
ffStrbufSetS(version, getenv("XONSH_VERSION"));
if (version->length) return true;
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL)
return false;
// xonsh/0.14.1
ffStrbufSubstrAfterFirstC(version, '/');
return true;
}
#ifdef _WIN32
static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
{
@@ -228,11 +245,8 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
return getExeVersionRaw(exe, version);
if(strcasecmp(exeName, "ash") == 0)
return getShellVersionAsh(exe, version);
if(strcasecmp(exeName, "python") == 0 && getenv("XONSH_VERSION"))
{
ffStrbufSetS(version, getenv("XONSH_VERSION"));
return true;
}
if(strcasecmp(exeName, "xonsh") == 0)
return getShellVersionXonsh(exe, version);
#ifdef _WIN32
if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0)
+4 -1
View File
@@ -5,12 +5,14 @@
typedef struct FFShellResult
{
FFstrbuf processName;
FFstrbuf exe;
FFstrbuf exe; //Actually arg0 in *nix
const char* exeName; //pointer to a char in exe
FFstrbuf exePath; //Full real path to executable file
FFstrbuf prettyName;
FFstrbuf version;
uint32_t pid;
uint32_t ppid;
int32_t tty;
} FFShellResult;
typedef struct FFTerminalResult
@@ -19,6 +21,7 @@ typedef struct FFTerminalResult
FFstrbuf exe;
FFstrbuf prettyName;
const char* exeName; //pointer to a char in exe
FFstrbuf exePath; //Full real path to executable file
FFstrbuf version;
uint32_t pid;
uint32_t ppid;
+124 -37
View File
@@ -4,14 +4,13 @@
#include "common/processing.h"
#include "common/thread.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __APPLE__
#include <libproc.h>
#elif defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <sys/types.h>
#include <sys/user.h>
#include <sys/sysctl.h>
@@ -25,38 +24,94 @@ static void setExeName(FFstrbuf* exe, const char** exeName)
*exeName = exe->chars + lastSlashIndex + 1;
}
static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, const char** exeName)
static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, const char** exeName, FFstrbuf* exePath)
{
assert(processName->length > 0);
ffStrbufClear(exe);
#ifdef __linux__
char cmdlineFilePath[64];
snprintf(cmdlineFilePath, sizeof(cmdlineFilePath), "/proc/%d/cmdline", (int)pid);
char filePath[64];
snprintf(filePath, sizeof(filePath), "/proc/%d/cmdline", (int)pid);
if(ffAppendFileBuffer(cmdlineFilePath, exe))
if(ffAppendFileBuffer(filePath, exe))
{
ffStrbufTrimRightSpace(exe);
ffStrbufSubstrBeforeFirstC(exe, '\0'); //Trim the arguments
ffStrbufTrimLeft(exe, '-'); //Happens in TTY
ffStrbufRecalculateLength(exe); //Trim the arguments
ffStrbufTrimLeft(exe, '-'); //Login shells start with a dash
}
snprintf(filePath, sizeof(filePath), "/proc/%d/exe", (int)pid);
ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX);
ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1);
if (length > 0) // doesn't contain trailing NUL
{
exePath->chars[length + 1] = '\0';
exePath->length = (uint32_t) length;
}
#elif defined(__APPLE__)
int length = proc_pidpath((int)pid, exe->chars, exe->allocated);
if(length > 0)
exe->length = (uint32_t)length;
size_t len = 0;
int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid };
if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), NULL, &len, NULL, 0) == 0)
{
FF_AUTO_FREE char* const procArgs2 = malloc(len);
if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), procArgs2, &len, NULL, 0) == 0)
{
// https://gist.github.com/nonowarn/770696#file-getargv-c-L46
uint32_t argc = *(uint32_t*) procArgs2;
const char* realExePath = procArgs2 + sizeof(argc);
const char* arg0 = memchr(realExePath, '\0', len - (size_t) (realExePath - procArgs2));
ffStrbufSetNS(exePath, (uint32_t) (arg0 - realExePath), realExePath);
do arg0++; while (*arg0 == '\0');
assert(arg0 < procArgs2 + len);
if (*arg0 == '-') arg0++; // Login shells
ffStrbufSetS(exe, arg0);
}
}
#elif defined(__FreeBSD__)
size_t size = exe->allocated;
if(!sysctl(
size_t size = ARG_MAX;
FF_AUTO_FREE char* args = malloc(size);
static_assert(ARG_MAX > PATH_MAX, "");
if(sysctl(
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}, 4,
exe->chars, &size,
args, &size,
NULL, 0
))
exe->length = (uint32_t)size - 1;
) == 0)
ffStrbufSetS(exePath, args);
size = ARG_MAX;
if(sysctl(
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_ARGS, pid}, 4,
args, &size,
NULL, 0
) == 0)
{
char* arg0 = args;
size_t arg0Len = strlen(args);
if (size > arg0Len + 1)
{
char* p = (char*) memrchr(args, '/', arg0Len);
if (p)
{
p++;
if (ffStrStartsWith(p, "python")) // /usr/local/bin/python3.9 /home/carter/.local/bin/xonsh
{
arg0 += arg0Len + 1;
}
}
}
if (arg0[0] == '-') arg0++;
ffStrbufSetS(exe, arg0);
}
#endif
@@ -66,7 +121,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex
setExeName(exe, exeName);
}
static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid, int32_t* tty)
{
#ifdef __linux__
@@ -79,21 +134,38 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
buf[nRead] = '\0';
*ppid = 0;
static_assert(sizeof(*ppid) == sizeof(int), "");
int tty_;
if(
sscanf(buf, "%*s (%255[^)]) %*c %d", name, ppid) != 2 || //stat (comm) state ppid
sscanf(buf, "%*s (%255[^)]) %*c %d %*d %*d %d", name, ppid, &tty_) < 2 || //stat (comm) state ppid pgrp session tty
!ffStrSet(name) ||
*ppid == 0
)
return "sscanf(stat) failed";
if (tty && (tty_ >> 8) == 0x88)
*tty = tty_ & 0xFF;
#elif defined(__APPLE__)
struct proc_bsdshortinfo proc;
if(proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) <= 0)
return "proc_pidinfo(pid) failed";
struct kinfo_proc proc;
size_t size = sizeof(proc);
if(sysctl(
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}, 4,
&proc, &size,
NULL, 0
))
return "sysctl(KERN_PROC_PID) failed";
*ppid = (pid_t)proc.pbsi_ppid;
strncpy(name, proc.pbsi_comm, 16); //trancated to 16 chars
*ppid = (pid_t)proc.kp_eproc.e_ppid;
strcpy(name, proc.kp_proc.p_comm); //trancated to 16 chars
if (tty)
{
*tty = ((proc.kp_eproc.e_tdev >> 24) & 0xFF) == 0x10
? proc.kp_eproc.e_tdev & 0xFFFFFF
: -1;
}
#elif defined(__FreeBSD__)
@@ -107,7 +179,20 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
return "sysctl(KERN_PROC_PID) failed";
*ppid = (pid_t)proc.ki_ppid;
strncpy(name, proc.ki_comm, COMMLEN);
strcpy(name, proc.ki_comm);
if (tty)
{
if (proc.ki_tdev != NODEV && proc.ki_flag & P_CONTROLT)
{
const char* ttyName = devname(proc.ki_tdev, S_IFCHR);
if (ffStrStartsWith(ttyName, "pts/"))
*tty = (int32_t) strtol(ttyName + strlen("pts/"), NULL, 10);
else
*tty = -1;
}
else
*tty = -1;
}
#else
@@ -125,7 +210,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
pid_t ppid = 0;
while (getProcessNameAndPpid(pid, name, &ppid) == NULL)
while (getProcessNameAndPpid(pid, name, &ppid, &result->tty) == NULL)
{
//Common programs that are between terminal and own process, but are not the shell
if(
@@ -153,7 +238,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
result->pid = (uint32_t) pid;
result->ppid = (uint32_t) ppid;
ffStrbufSetS(&result->processName, name);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName, &result->exePath);
break;
}
return ppid;
@@ -166,7 +251,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
pid_t ppid = 0;
while (getProcessNameAndPpid(pid, name, &ppid) == NULL)
while (getProcessNameAndPpid(pid, name, &ppid, NULL) == NULL)
{
//Known shells
if (
@@ -185,7 +270,9 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrEquals(name, "git-shell") ||
ffStrEquals(name, "elvish") ||
ffStrEquals(name, "oil.ovm") ||
(ffStrEquals(name, "python") && getenv("XONSH_VERSION"))
ffStrEquals(name, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
ffStrEquals(name, "login") ||
ffStrEndsWith(name, ".sh")
)
{
pid = ppid;
@@ -196,14 +283,15 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
// https://github.com/fastfetch-cli/fastfetch/discussions/501
if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)"))
{
if (__builtin_expect(getProcessNameAndPpid(ppid, name, &ppid) != NULL, false))
if (__builtin_expect(getProcessNameAndPpid(ppid, name, &ppid, NULL) != NULL, false))
return 0;
}
#endif
result->pid = (uint32_t) pid;
result->ppid = (uint32_t) ppid;
ffStrbufSetS(&result->processName, name);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName, &result->exePath);
break;
}
return ppid;
@@ -316,8 +404,6 @@ static void setShellInfoDetails(FFShellResult* result)
ffStrbufInitStatic(&result->prettyName, "PowerShell");
else if(ffStrbufEqualS(&result->processName, "nu"))
ffStrbufInitStatic(&result->prettyName, "nushell");
else if(ffStrbufEqualS(&result->processName, "python") && getenv("XONSH_VERSION"))
ffStrbufInitStatic(&result->prettyName, "xonsh");
else if(ffStrbufEqualS(&result->processName, "oil.ovm"))
ffStrbufInitStatic(&result->prettyName, "Oils");
else
@@ -377,13 +463,10 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
else
ffStrbufInitCopy(&result->prettyName, &result->processName);
ffStrbufInit(&result->version);
fftsGetTerminalVersion(&result->processName, &result->exe, &result->version);
}
#ifdef __APPLE__
#define FF_EXE_PATH_LEN PROC_PIDPATHINFO_MAXSIZE
#elif defined(MAXPATH)
#if defined(MAXPATH)
#define FF_EXE_PATH_LEN MAXPATH
#elif defined(PATH_MAX)
#define FF_EXE_PATH_LEN PATH_MAX
@@ -402,9 +485,11 @@ const FFShellResult* ffDetectShell()
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, FF_EXE_PATH_LEN);
result.exeName = result.exe.chars;
ffStrbufInit(&result.exePath);
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
result.tty = -1;
pid_t ppid = getppid();
ppid = getShellInfo(&result, ppid);
@@ -425,6 +510,8 @@ const FFTerminalResult* ffDetectTerminal()
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, FF_EXE_PATH_LEN);
result.exeName = result.exe.chars;
ffStrbufInit(&result.exePath);
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
@@ -39,15 +39,18 @@ static bool getProductVersion(const wchar_t* filePath, FFstrbuf* version)
return false;
}
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName)
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName, FFstrbuf* exePath, bool* gui)
{
HANDLE hProcess = pid == 0
FF_AUTO_CLOSE_FD HANDLE hProcess = pid == 0
? GetCurrentProcess()
: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, pid);
if (gui)
*gui = GetGuiResources(hProcess, GR_GDIOBJECTS) > 0;
if(ppid)
{
PROCESS_BASIC_INFORMATION info;
PROCESS_BASIC_INFORMATION info = {};
ULONG size;
if(NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessBasicInformation, &info, sizeof(info), &size)))
{
@@ -55,21 +58,20 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
*ppid = (uint32_t)info.InheritedFromUniqueProcessId;
}
else
{
CloseHandle(hProcess);
return false;
}
}
if(exe)
{
DWORD bufSize = exe->allocated;
if(QueryFullProcessImageNameA(hProcess, 0, exe->chars, &bufSize))
exe->length = bufSize;
else
{
CloseHandle(hProcess);
return false;
// We use full path here
// Querying command line of remote processes in Windows requires either WMI or ReadProcessMemory
exe->length = bufSize;
if (exePath) ffStrbufSet(exePath, exe);
}
else
return false;
}
if(pname && exeName)
{
@@ -77,7 +79,6 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
ffStrbufSetS(pname, *exeName);
}
CloseHandle(hProcess);
return true;
}
@@ -85,9 +86,9 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
{
uint32_t ppid;
uint32_t ppid = 0;
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName))
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName, &result->exePath, NULL))
{
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
@@ -103,7 +104,8 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "guake-wrapped") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || //scoop warps the real binaries with a "shim" exe
ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables
ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || // scoop warps the real binaries with a "shim" exe
ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") ||
ffStrbufContainIgnCaseS(&result->prettyName, "debug") ||
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014
@@ -116,9 +118,6 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
continue;
}
ffStrbufClear(&result->version);
fftsGetShellVersion(&result->exe, result->prettyName.chars, &result->version);
result->pid = pid;
result->ppid = ppid;
@@ -187,7 +186,7 @@ static bool getTerminalFromEnv(FFTerminalResult* result)
//ConEmu
uint32_t pid = (uint32_t) strtoul(term, NULL, 10);
result->pid = pid;
if(getProcessInfo(pid, NULL, &result->processName, &result->exe, &result->exeName))
if(getProcessInfo(pid, NULL, &result->processName, &result->exe, &result->exeName, &result->exePath, NULL))
{
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
@@ -243,12 +242,8 @@ static bool detectDefaultTerminal(FFTerminalResult* result)
DWORD bufSize = 80;
if (RegGetValueW(HKEY_CURRENT_USER, L"Console\\%%Startup", L"DelegationTerminal", RRF_RT_REG_SZ, NULL, uuid, &bufSize) == ERROR_SUCCESS)
{
if(wcscmp(uuid, L"{00000000-0000-0000-0000-000000000000}") == 0)
{
// Let Windows decide
return false;
}
if(wcscmp(uuid, L"{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}") == 0)
if(wcscmp(uuid, L"{00000000-0000-0000-0000-000000000000}") == 0 || // Let Windows decide
wcscmp(uuid, L"{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}") == 0) // Conhost
{
goto conhost;
}
@@ -296,27 +291,13 @@ conhost:
static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
{
uint32_t ppid;
uint32_t ppid = 0;
bool hasGui;
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName))
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName, &result->exePath, &hasGui))
{
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4);
if(
ffStrbufIgnCaseEqualS(&result->prettyName, "pwsh") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "cmd") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "bash") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "zsh") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "fish") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "nu") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "powershell") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "powershell_ise") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "wsl") || // running inside wsl
ffStrbufIgnCaseEqualS(&result->prettyName, "servercoreshell") || // ServerCore Shell Launcher
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmuC") // wrapper process of ConEmu
) {
if(!hasGui)
{
//We are nested shell
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
@@ -326,20 +307,21 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
continue;
}
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4);
if(ffStrbufIgnCaseEqualS(&result->prettyName, "sihost") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "explorer")
) {
// A CUI program created by Windows Explorer will spawn a conhost as its child.
// However the conhost process is just a placeholder;
// The true terminal can be Windows Terminal or others.
if (!getTerminalFromEnv(result) && !detectDefaultTerminal(result))
{
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
result->exeName = "";
return 0;
}
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
result->exeName = "";
return 0;
}
else
{
@@ -380,19 +362,30 @@ const FFShellResult* ffDetectShell(void)
init = true;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, 128);
ffStrbufInitA(&result.exe, MAX_PATH);
result.exeName = "";
ffStrbufInit(&result.exePath);
ffStrbufInit(&result.prettyName);
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
result.tty = -1;
uint32_t ppid;
if(!getProcessInfo(0, &ppid, NULL, NULL, NULL))
if(!getProcessInfo(0, &ppid, NULL, NULL, NULL, NULL, NULL))
return &result;
ppid = getShellInfo(&result, ppid);
setShellInfoDetails(&result);
if (result.processName.length > 0)
{
setShellInfoDetails(&result);
char tmp[MAX_PATH];
strcpy(tmp, result.exeName);
char* ext = strrchr(tmp, '.');
if (ext) *ext = '\0';
fftsGetShellVersion(&result.exe, tmp, &result.version);
}
return &result;
}
@@ -406,8 +399,9 @@ const FFTerminalResult* ffDetectTerminal(void)
init = true;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, 128);
ffStrbufInitA(&result.exe, MAX_PATH);
result.exeName = "";
ffStrbufInit(&result.exePath);
ffStrbufInit(&result.prettyName);
ffStrbufInit(&result.version);
result.pid = 0;
@@ -419,10 +413,14 @@ const FFTerminalResult* ffDetectTerminal(void)
if(result.processName.length == 0)
getTerminalFromEnv(&result);
if(result.processName.length == 0)
detectDefaultTerminal(&result);
setTerminalInfoDetails(&result);
fftsGetTerminalVersion(&result.processName, &result.exe, &result.version);
if(result.processName.length > 0)
{
setTerminalInfoDetails(&result);
fftsGetTerminalVersion(&result.processName, &result.exe, &result.version);
}
return &result;
}
+9 -1
View File
@@ -7,6 +7,7 @@
#include "common/jsonconfig.h"
#include "detection/version/version.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include "logo/logo.h"
#include "fastfetch_datatext.h"
@@ -831,7 +832,14 @@ static void writeConfigFile(FFdata* data, const FFstrbuf* filename)
yyjson_mut_write_fp(stdout, doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL);
else
{
if (yyjson_mut_write_file(filename->chars, doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL))
size_t len;
FF_AUTO_FREE const char* str = yyjson_mut_write(doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, &len);
if (!str)
{
printf("Error: failed to generate config file\n");
exit(1);
}
if (ffWriteFileData(filename->chars, len, str))
printf("The generated config file has been written in `%s`\n", filename->chars);
else
{
+13 -9
View File
@@ -1,6 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/bar.h"
#include "common/percent.h"
#include "common/parsing.h"
#include "detection/battery/battery.h"
#include "modules/battery/battery.h"
@@ -24,12 +24,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
{
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
if(result->capacity <= 20)
ffAppendPercentBar(&str, result->capacity, 100, 100, 0);
else if(result->capacity <= 50)
ffAppendPercentBar(&str, result->capacity, 100, 0, 100);
else
ffAppendPercentBar(&str, result->capacity, 0, 100, 100);
ffPercentAppendBar(&str, result->capacity, options->percent);
}
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
@@ -37,7 +32,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
if(str.length > 0)
ffStrbufAppendC(&str, ' ');
ffAppendPercentNum(&str, result->capacity, 51, 21, str.length > 0);
ffPercentAppendNum(&str, result->capacity, options->percent, str.length > 0);
}
}
@@ -62,7 +57,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
else
{
FF_STRBUF_AUTO_DESTROY capacityStr = ffStrbufCreate();
ffAppendPercentNum(&capacityStr, result->capacity, 51, 21, false);
ffPercentAppendNum(&capacityStr, result->capacity, options->percent, false);
ffPrintFormat(FF_BATTERY_MODULE_NAME, index, &options->moduleArgs, FF_BATTERY_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName},
@@ -127,6 +122,9 @@ bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, co
}
#endif
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -157,6 +155,9 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module)
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -175,6 +176,8 @@ void ffGenerateBatteryJsonConfig(FFBatteryOptions* options, yyjson_mut_doc* doc,
if (options->temp != defaultOptions.temp)
yyjson_mut_obj_add_bool(doc, module, "temp", options->temp);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -245,6 +248,7 @@ void ffInitBatteryOptions(FFBatteryOptions* options)
);
ffOptionInitModuleArg(&options->moduleArgs);
options->temp = false;
options->percent = (FFPercentConfig) { 50, 20 };
#ifdef _WIN32
options->useSetupApi = false;
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFBatteryOptions
{
@@ -10,6 +11,7 @@ typedef struct FFBatteryOptions
FFModuleArgs moduleArgs;
bool temp;
FFPercentConfig percent;
#ifdef _WIN32
bool useSetupApi;
+24 -8
View File
@@ -1,3 +1,4 @@
#include "common/percent.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/bluetooth/bluetooth.h"
@@ -11,23 +12,29 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&device->name, stdout);
if(device->battery > 0)
printf(" (%d%%)", device->battery);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name);
if(!device->connected)
puts(" [disconnected]");
else
putchar('\n');
if (device->battery > 0 && device->battery <= 100)
{
if (buffer.length)
ffStrbufAppendC(&buffer, ' ');
ffPercentAppendNum(&buffer, device->battery, options->percent, buffer.length > 0);
}
if (!device->connected)
ffStrbufAppendS(&buffer, " [disconnected]");
}
else
{
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
ffPercentAppendNum(&percentageStr, device->battery, options->percent, false);
ffPrintFormat(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_BLUETOOTH_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->address},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->type},
{FF_FORMAT_ARG_TYPE_UINT8, &device->battery}
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr}
});
}
}
@@ -86,6 +93,9 @@ bool ffParseBluetoothCommandOptions(FFBluetoothOptions* options, const char* key
return true;
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -108,6 +118,9 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module)
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -121,6 +134,8 @@ void ffGenerateBluetoothJsonConfig(FFBluetoothOptions* options, yyjson_mut_doc*
if (options->showDisconnected != defaultOptions.showDisconnected)
yyjson_mut_obj_add_bool(doc, module, "showDisconnected", options->showDisconnected);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -181,6 +196,7 @@ void ffInitBluetoothOptions(FFBluetoothOptions* options)
);
ffOptionInitModuleArg(&options->moduleArgs);
options->showDisconnected = false;
options->percent = (FFPercentConfig) { 50, 20 };
}
void ffDestroyBluetoothOptions(FFBluetoothOptions* options)
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFBluetoothOptions
{
@@ -10,4 +11,5 @@ typedef struct FFBluetoothOptions
FFModuleArgs moduleArgs;
bool showDisconnected;
FFPercentConfig percent;
} FFBluetoothOptions;
+13 -4
View File
@@ -1,4 +1,4 @@
#include "common/bar.h"
#include "common/percent.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/brightness/brightness.h"
@@ -52,7 +52,7 @@ void ffPrintBrightness(FFBrightnessOptions* options)
if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
ffAppendPercentBar(&str, percent, 0, 100, 100);
ffPercentAppendBar(&str, percent, options->percent);
}
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
@@ -60,7 +60,7 @@ void ffPrintBrightness(FFBrightnessOptions* options)
if(str.length > 0)
ffStrbufAppendC(&str, ' ');
ffAppendPercentNum(&str, percent, 10, 10, str.length > 0);
ffPercentAppendNum(&str, percent, options->percent, str.length > 0);
}
ffStrbufPutTo(&str, stdout);
@@ -68,7 +68,7 @@ void ffPrintBrightness(FFBrightnessOptions* options)
else
{
FF_STRBUF_AUTO_DESTROY valueStr = ffStrbufCreate();
ffAppendPercentNum(&valueStr, percent, 10, 10, false);
ffPercentAppendNum(&valueStr, percent, options->percent, false);
ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BRIGHTNESS_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &valueStr},
{FF_FORMAT_ARG_TYPE_STRBUF, &item->name},
@@ -97,6 +97,9 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k
return true;
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -119,6 +122,9 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -132,6 +138,8 @@ void ffGenerateBrightnessJsonConfig(FFBrightnessOptions* options, yyjson_mut_doc
if (defaultOptions.ddcciSleep != options->ddcciSleep)
yyjson_mut_obj_add_uint(doc, module, "ddcciSleep", options->ddcciSleep);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -197,6 +205,7 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options)
ffOptionInitModuleArg(&options->moduleArgs);
options->ddcciSleep = 10;
options->percent = (FFPercentConfig) { 100, 100 };
}
void ffDestroyBrightnessOptions(FFBrightnessOptions* options)
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFBrightnessOptions
{
@@ -10,4 +11,5 @@ typedef struct FFBrightnessOptions
FFModuleArgs moduleArgs;
uint32_t ddcciSleep; // ms
FFPercentConfig percent;
} FFBrightnessOptions;
+16 -7
View File
@@ -1,6 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/bar.h"
#include "common/percent.h"
#include "detection/cpuusage/cpuusage.h"
#include "modules/cpuusage/cpuusage.h"
#include "util/stringUtils.h"
@@ -52,12 +52,12 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
if (!options->separate)
{
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
ffAppendPercentBar(&str, avgValue, 0, 50, 80);
ffPercentAppendBar(&str, avgValue, options->percent);
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
{
if(str.length > 0)
ffStrbufAppendC(&str, ' ');
ffAppendPercentNum(&str, avgValue, 50, 80, str.length > 0);
ffPercentAppendNum(&str, avgValue, options->percent, str.length > 0);
}
}
else
@@ -66,7 +66,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
{
if(str.length > 0)
ffStrbufAppendC(&str, ' ');
ffAppendPercentNum(&str, *percent, 50, 80, false);
ffPercentAppendNum(&str, *percent, options->percent, false);
}
}
ffStrbufPutTo(&str, stdout);
@@ -74,11 +74,11 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
else
{
FF_STRBUF_AUTO_DESTROY avgStr = ffStrbufCreate();
ffAppendPercentNum(&avgStr, avgValue, 50, 80, false);
ffPercentAppendNum(&avgStr, avgValue, options->percent, false);
FF_STRBUF_AUTO_DESTROY minStr = ffStrbufCreate();
ffAppendPercentNum(&minStr, minValue, 50, 80, false);
ffPercentAppendNum(&minStr, minValue, options->percent, false);
FF_STRBUF_AUTO_DESTROY maxStr = ffStrbufCreate();
ffAppendPercentNum(&maxStr, maxValue, 50, 80, false);
ffPercentAppendNum(&maxStr, maxValue, options->percent, false);
ffPrintFormat(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_CPUUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &avgStr},
{FF_FORMAT_ARG_TYPE_STRBUF, &maxStr},
@@ -102,6 +102,9 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key,
return true;
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -124,6 +127,9 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module)
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -137,6 +143,8 @@ void ffGenerateCPUUsageJsonConfig(FFCPUUsageOptions* options, yyjson_mut_doc* do
if (options->separate != defaultOptions.separate)
yyjson_mut_obj_add_bool(doc, module, "separate", options->separate);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateCPUUsageJsonResult(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -182,6 +190,7 @@ void ffInitCPUUsageOptions(FFCPUUsageOptions* options)
);
ffOptionInitModuleArg(&options->moduleArgs);
options->separate = false;
options->percent = (FFPercentConfig) { 50, 80 };
}
void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options)
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFCPUUsageOptions
{
@@ -10,4 +11,5 @@ typedef struct FFCPUUsageOptions
FFModuleArgs moduleArgs;
bool separate;
FFPercentConfig percent;
} FFCPUUsageOptions;
+14 -5
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/bar.h"
#include "common/percent.h"
#include "detection/disk/disk.h"
#include "modules/disk/disk.h"
#include "util/stringUtils.h"
@@ -59,7 +59,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
{
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
ffAppendPercentBar(&str, bytesPercentage, 0, 50, 80);
ffPercentAppendBar(&str, bytesPercentage, options->percent);
ffStrbufAppendC(&str, ' ');
}
@@ -68,7 +68,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
{
ffAppendPercentNum(&str, bytesPercentage, 50, 80, str.length > 0);
ffPercentAppendNum(&str, bytesPercentage, options->percent, str.length > 0);
ffStrbufAppendC(&str, ' ');
}
}
@@ -104,10 +104,10 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
else
{
FF_STRBUF_AUTO_DESTROY bytesPercentageStr = ffStrbufCreate();
ffAppendPercentNum(&bytesPercentageStr, bytesPercentage, 50, 80, false);
ffPercentAppendNum(&bytesPercentageStr, bytesPercentage, options->percent, false);
FF_STRBUF_AUTO_DESTROY filesPercentageStr = ffStrbufCreate();
double filesPercentage = disk->filesTotal > 0 ? ((double) disk->filesUsed / (double) disk->filesTotal) * 100.0 : 0;
ffAppendPercentNum(&filesPercentageStr, filesPercentage, 50, 80, false);
ffPercentAppendNum(&filesPercentageStr, filesPercentage, options->percent, false);
bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT);
bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT);
@@ -278,6 +278,9 @@ bool ffParseDiskCommandOptions(FFDiskOptions* options, const char* key, const ch
return true;
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -354,6 +357,9 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module)
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -388,6 +394,8 @@ void ffGenerateDiskJsonConfig(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso
if (defaultOptions.calcType != options->calcType)
yyjson_mut_obj_add_bool(doc, module, "useAvailable", options->calcType == FF_DISK_CALC_TYPE_AVAILABLE);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -476,6 +484,7 @@ void ffInitDiskOptions(FFDiskOptions* options)
ffStrbufInit(&options->folders);
options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT;
options->calcType = FF_DISK_CALC_TYPE_FREE;
options->percent = (FFPercentConfig) { 50, 80 };
}
void ffDestroyDiskOptions(FFDiskOptions* options)
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef enum FFDiskVolumeType
{
@@ -29,4 +30,5 @@ typedef struct FFDiskOptions
FFstrbuf folders;
FFDiskVolumeType showTypes;
FFDiskCalcType calcType;
FFPercentConfig percent;
} FFDiskOptions;
+22 -7
View File
@@ -1,4 +1,4 @@
#include "common/bar.h"
#include "common/percent.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/gamepad/gamepad.h"
@@ -11,21 +11,27 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device
{
if(options->moduleArgs.outputFormat.length == 0)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name);
ffPrintLogoAndKey(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name);
if (device->battery > 0 && device->battery <= 100)
{
ffStrbufAppendC(&buffer, ' ');
ffAppendPercentNum(&buffer, device->battery, 51, 21, true);
if (buffer.length)
ffStrbufAppendC(&buffer, ' ');
ffPercentAppendNum(&buffer, device->battery, options->percent, buffer.length > 0);
}
ffStrbufPutTo(&buffer, stdout);
}
else
{
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
ffPercentAppendNum(&percentageStr, device->battery, options->percent, false);
ffPrintFormat(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->serial},
{FF_FORMAT_ARG_TYPE_UINT8, &device->battery},
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr},
});
}
}
@@ -64,6 +70,9 @@ bool ffParseGamepadCommandOptions(FFGamepadOptions* options, const char* key, co
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -80,6 +89,9 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module)
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -90,6 +102,8 @@ void ffGenerateGamepadJsonConfig(FFGamepadOptions* options, yyjson_mut_doc* doc,
ffInitGamepadOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -127,10 +141,10 @@ void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
void ffPrintGamepadHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_GAMEPAD_MODULE_NAME, "{1}", FF_GAMEPAD_NUM_FORMAT_ARGS, (const char* []) {
ffPrintModuleFormatHelp(FF_GAMEPAD_MODULE_NAME, "{1} ({3})", FF_GAMEPAD_NUM_FORMAT_ARGS, (const char* []) {
"Name",
"Serial number",
"Battery",
"Battery percentage",
});
}
@@ -148,6 +162,7 @@ void ffInitGamepadOptions(FFGamepadOptions* options)
ffGenerateGamepadJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs);
options->percent = (FFPercentConfig) { 50, 20 };
}
void ffDestroyGamepadOptions(FFGamepadOptions* options)
+2
View File
@@ -8,4 +8,6 @@ typedef struct FFGamepadOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
FFPercentConfig percent;
} FFGamepadOptions;
+11 -2
View File
@@ -1,4 +1,4 @@
#include "common/bar.h"
#include "common/percent.h"
#include "common/parsing.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
@@ -60,7 +60,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
{
ffStrbufAppendS(&output, ", ");
ffAppendPercentNum(&output, (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0, 50, 80, false);
ffPercentAppendNum(&output, (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0, options->percent, false);
}
ffStrbufAppendC(&output, ')');
}
@@ -162,6 +162,9 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char
});
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -212,6 +215,9 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module)
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -247,6 +253,8 @@ void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
break;
}
}
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -363,6 +371,7 @@ void ffInitGPUOptions(FFGPUOptions* options)
options->forceVulkan = false;
options->temp = false;
options->hideType = FF_GPU_TYPE_UNKNOWN;
options->percent = (FFPercentConfig) { 50, 80 };
}
void ffDestroyGPUOptions(FFGPUOptions* options)
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef enum FFGPUType
{
@@ -20,4 +21,5 @@ typedef struct FFGPUOptions
bool temp;
bool driverSpecific;
bool forceVulkan;
FFPercentConfig percent;
} FFGPUOptions;
+13 -4
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/bar.h"
#include "common/percent.h"
#include "detection/memory/memory.h"
#include "modules/memory/memory.h"
#include "util/stringUtils.h"
@@ -40,7 +40,7 @@ void ffPrintMemory(FFMemoryOptions* options)
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
ffAppendPercentBar(&str, percentage, 0, 50, 80);
ffPercentAppendBar(&str, percentage, options->percent);
ffStrbufAppendC(&str, ' ');
}
@@ -48,7 +48,7 @@ void ffPrintMemory(FFMemoryOptions* options)
ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars);
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
ffAppendPercentNum(&str, percentage, 50, 80, str.length > 0);
ffPercentAppendNum(&str, percentage, options->percent, str.length > 0);
ffStrbufTrimRight(&str, ' ');
ffStrbufPutTo(&str, stdout);
@@ -57,7 +57,7 @@ void ffPrintMemory(FFMemoryOptions* options)
else
{
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
ffAppendPercentNum(&percentageStr, percentage, 50, 80, false);
ffPercentAppendNum(&percentageStr, percentage, options->percent, false);
ffPrintFormat(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
@@ -73,6 +73,9 @@ bool ffParseMemoryCommandOptions(FFMemoryOptions* options, const char* key, cons
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -89,6 +92,9 @@ void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module)
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -99,6 +105,8 @@ void ffGenerateMemoryJsonConfig(FFMemoryOptions* options, yyjson_mut_doc* doc, y
ffInitMemoryOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateMemoryJsonResult(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -140,6 +148,7 @@ void ffInitMemoryOptions(FFMemoryOptions* options)
ffGenerateMemoryJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs);
options->percent = (FFPercentConfig) { 50, 80 };
}
void ffDestroyMemoryOptions(FFMemoryOptions* options)
+3
View File
@@ -3,9 +3,12 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFMemoryOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
FFPercentConfig percent;
} FFMemoryOptions;
+12 -3
View File
@@ -38,6 +38,8 @@ void ffPrintShell(FFShellOptions* options)
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
{FF_FORMAT_ARG_TYPE_UINT, &result->pid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->exePath},
{FF_FORMAT_ARG_TYPE_INT, &result->tty},
});
}
}
@@ -90,21 +92,28 @@ void ffGenerateShellJsonResult(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_m
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->exe);
yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->exeName);
yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &result->exePath);
yyjson_mut_obj_add_uint(doc, obj, "pid", result->pid);
yyjson_mut_obj_add_uint(doc, obj, "ppid", result->ppid);
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->processName);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->prettyName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->version);
if (result->tty >= 0)
yyjson_mut_obj_add_int(doc, obj, "tty", result->tty);
else
yyjson_mut_obj_add_null(doc, obj, "tty");
}
void ffPrintShellHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_SHELL_MODULE_NAME, "{3} {4}", FF_SHELL_NUM_FORMAT_ARGS, (const char* []) {
"Shell process name",
"Shell path with exe name",
"Shell exe name",
"The first argument of the command line when running the shell",
"Shell base name of arg0",
"Shell version",
"Shell pid",
"Shell pretty name"
"Shell pretty name",
"Shell full exe path",
});
}
+2
View File
@@ -3,6 +3,7 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef enum FFSoundType
{
@@ -17,4 +18,5 @@ typedef struct FFSoundOptions
FFModuleArgs moduleArgs;
FFSoundType soundType;
FFPercentConfig percent;
} FFSoundOptions;
+39 -9
View File
@@ -1,3 +1,4 @@
#include "common/percent.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/sound/sound.h"
@@ -11,27 +12,47 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&device->name, stdout);
FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate();
if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
ffStrbufAppend(&str, &device->name);
if(device->volume != FF_SOUND_VOLUME_UNKNOWN)
{
if(device->volume > 0)
printf(" (%d%%)", device->volume);
else
fputs(" (muted)", stdout);
if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
if (str.length)
ffStrbufAppendC(&str, ' ');
ffPercentAppendBar(&str, device->volume, options->percent);
}
if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
{
if (str.length)
ffStrbufAppendC(&str, ' ');
ffPercentAppendNum(&str, device->volume, options->percent, str.length > 0);
}
}
if(device->main && index > 0)
fputs(" (*)", stdout);
if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
{
if (device->main && index > 0)
ffStrbufAppendS(&str, " (*)");
}
putchar('\n');
ffStrbufPutTo(&str, stdout);
}
else
{
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
ffPercentAppendNum(&percentageStr, device->volume, options->percent, false);
ffPrintFormat(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_SOUND_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_BOOL, &device->main},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_UINT8, &device->volume},
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier}
});
}
@@ -100,6 +121,9 @@ bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const
return true;
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -132,6 +156,9 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module)
continue;
}
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -158,6 +185,8 @@ void ffGenerateSoundJsonConfig(FFSoundOptions* options, yyjson_mut_doc* doc, yyj
break;
}
}
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -226,6 +255,7 @@ void ffInitSoundOptions(FFSoundOptions* options)
ffOptionInitModuleArg(&options->moduleArgs);
options->soundType = FF_SOUND_TYPE_MAIN;
options->percent = (FFPercentConfig) { 80, 90 };
}
void ffDestroySoundOptions(FFSoundOptions* options)
+3
View File
@@ -3,9 +3,12 @@
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFSwapOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
FFPercentConfig percent;
} FFSwapOptions;
+16 -5
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/bar.h"
#include "common/percent.h"
#include "detection/swap/swap.h"
#include "modules/swap/swap.h"
#include "util/stringUtils.h"
@@ -37,17 +37,19 @@ void ffPrintSwap(FFSwapOptions* options)
{
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
ffAppendPercentBar(&str, 0, 0, 50, 80);
ffPercentAppendBar(&str, 0, options->percent);
ffStrbufAppendC(&str, ' ');
}
if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
ffStrbufAppendS(&str, "Disabled");
else
ffPercentAppendNum(&str, 0, options->percent, str.length > 0);
}
else
{
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
{
ffAppendPercentBar(&str, percentage, 0, 50, 80);
ffPercentAppendBar(&str, percentage, options->percent);
ffStrbufAppendC(&str, ' ');
}
@@ -55,7 +57,7 @@ void ffPrintSwap(FFSwapOptions* options)
ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars);
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
ffAppendPercentNum(&str, percentage, 50, 80, str.length > 0);
ffPercentAppendNum(&str, percentage, options->percent, str.length > 0);
}
ffStrbufTrimRight(&str, ' ');
@@ -64,7 +66,7 @@ void ffPrintSwap(FFSwapOptions* options)
else
{
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
ffAppendPercentNum(&percentageStr, percentage, 50, 80, false);
ffPercentAppendNum(&percentageStr, percentage, options->percent, false);
ffPrintFormat(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_SWAP_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
@@ -80,6 +82,9 @@ bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const ch
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
return false;
}
@@ -96,6 +101,9 @@ void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module)
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -105,6 +113,8 @@ void ffGenerateSwapJsonConfig(FFSwapOptions* options, yyjson_mut_doc* doc, yyjso
__attribute__((__cleanup__(ffDestroySwapOptions))) FFSwapOptions defaultOptions;
ffInitSwapOptions(&defaultOptions);
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
}
@@ -147,6 +157,7 @@ void ffInitSwapOptions(FFSwapOptions* options)
ffGenerateSwapJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs);
options->percent = (FFPercentConfig) { 50, 80 };
}
void ffDestroySwapOptions(FFSwapOptions* options)
+7 -4
View File
@@ -6,7 +6,7 @@
#include <string.h>
#define FF_TERMINAL_NUM_FORMAT_ARGS 6
#define FF_TERMINAL_NUM_FORMAT_ARGS 7
void ffPrintTerminal(FFTerminalOptions* options)
{
@@ -36,6 +36,7 @@ void ffPrintTerminal(FFTerminalOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &result->pid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->exePath},
});
}
}
@@ -89,6 +90,7 @@ void ffGenerateTerminalJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yy
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->processName);
yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->exe);
yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->exeName);
yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &result->exePath);
yyjson_mut_obj_add_uint(doc, obj, "pid", result->pid);
yyjson_mut_obj_add_uint(doc, obj, "ppid", result->ppid);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->prettyName);
@@ -99,11 +101,12 @@ void ffPrintTerminalHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_TERMINAL_MODULE_NAME, "{5} {6}", FF_TERMINAL_NUM_FORMAT_ARGS, (const char* []) {
"Terminal process name",
"Terminal path with exe name",
"Terminal exe name",
"The first argument of the command line when running the terminal",
"Terminal base name of arg0",
"Terminal pid",
"Terminal pretty name",
"Terminal version"
"Terminal version",
"Terminal full exe path",
});
}
+36 -4
View File
@@ -1,4 +1,5 @@
#include "fastfetch.h"
#include "common/color.h"
#include "common/jsonconfig.h"
#include "util/stringUtils.h"
#include "options/display.h"
@@ -118,6 +119,22 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->percentNdigits = (uint8_t) yyjson_get_uint(ndigits);
yyjson_val* color = yyjson_obj_get(val, "color");
if (color)
{
if (!yyjson_is_obj(color))
return "display.percent.color must be an object";
yyjson_val* green = yyjson_obj_get(color, "green");
if (green) ffOptionParseColor(yyjson_get_str(green), &options->percentColorGreen);
yyjson_val* yellow = yyjson_obj_get(color, "yellow");
if (yellow) ffOptionParseColor(yyjson_get_str(yellow), &options->percentColorYellow);
yyjson_val* red = yyjson_obj_get(color, "red");
if (red) ffOptionParseColor(yyjson_get_str(red), &options->percentColorRed);
}
}
else if (ffStrEqualsIgnCase(key, "bar"))
{
@@ -248,10 +265,22 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
{},
});
}
else if(ffStrEqualsIgnCase(key, "--percent-type"))
options->percentType = (uint8_t) ffOptionParseUInt32(key, value);
else if(ffStrEqualsIgnCase(key, "--percent-ndigits"))
options->percentNdigits = (uint8_t) ffOptionParseUInt32(key, value);
else if(ffStrStartsWithIgnCase(key, "--percent-"))
{
const char* subkey = key + strlen("--percent-");
if(ffStrEqualsIgnCase(subkey, "type"))
options->percentType = (uint8_t) ffOptionParseUInt32(key, value);
else if(ffStrEqualsIgnCase(subkey, "ndigits"))
options->percentNdigits = (uint8_t) ffOptionParseUInt32(key, value);
else if(ffStrEqualsIgnCase(subkey, "color-green"))
ffOptionParseColor(value, &options->percentColorGreen);
else if(ffStrEqualsIgnCase(subkey, "color-yellow"))
ffOptionParseColor(value, &options->percentColorYellow);
else if(ffStrEqualsIgnCase(subkey, "color-red"))
ffOptionParseColor(value, &options->percentColorRed);
else
return false;
}
else if(ffStrEqualsIgnCase(key, "--no-buffer"))
options->noBuffer = ffOptionParseBoolean(value);
else if(ffStrStartsWithIgnCase(key, "--bar-"))
@@ -305,6 +334,9 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options)
options->barBorder = true;
options->percentType = 9;
options->percentNdigits = 0;
ffStrbufInitStatic(&options->percentColorGreen, FF_COLOR_FG_GREEN);
ffStrbufInitStatic(&options->percentColorYellow, FF_COLOR_FG_LIGHT_YELLOW);
ffStrbufInitStatic(&options->percentColorRed, FF_COLOR_FG_LIGHT_RED);
}
void ffOptionsDestroyDisplay(FFOptionsDisplay* options)
+3
View File
@@ -41,6 +41,9 @@ typedef struct FFOptionsDisplay
bool barBorder;
uint8_t percentType;
uint8_t percentNdigits;
FFstrbuf percentColorGreen;
FFstrbuf percentColorYellow;
FFstrbuf percentColorRed;
bool noBuffer;
uint32_t keyWidth;
} FFOptionsDisplay;
+1 -1
View File
@@ -6,7 +6,7 @@
#include <stdlib.h>
#include <assert.h>
static inline void ffWrapFree(void* pPtr)
static inline void ffWrapFree(const void* pPtr)
{
assert(pPtr);
if(*(void**)pPtr)