Compare commits

...

28 Commits

Author SHA1 Message Date
Carter Li b81c4a04db Merge pull request #2164 from fastfetch-cli/dev
Release: v2.58.0
2026-01-21 15:03:51 +08:00
李通洲 e26a05e3ac DE (Linux): ensures process returns successfully before using its output 2026-01-21 14:28:40 +08:00
李通洲 f08a1fb0b4 Release: v2.58.0 2026-01-21 14:12:53 +08:00
李通洲 2a82009ffe WM (macOS): checks the version of WindowServer instead of WindowManager 2026-01-21 09:39:31 +08:00
李通洲 e851f3a7ed Packages (Linux): optimises pacman detection code 2026-01-20 10:06:02 +08:00
Sean Will 3a865df09e Packages (Linux): Auto detect the DBPath directory for pacman on archlinux (#2154)
Fixes #2068
2026-01-19 19:44:30 -06:00
berezka bae80e2932 Add new KISS Linux logo based off favicon 2026-01-20 09:42:28 +08:00
berezka 4445e1e78d Fix Bedrock Linux version detection & futureproof for 0.8 2026-01-20 09:42:28 +08:00
Carter Li f0e3d3d8e1 Host (Linux): uses /sys/firmware/devicetree/base/smbios if available 2026-01-20 09:20:48 +08:00
Carter Li a313fd1572 Linux: uses the standard /sys/firmware/devicetree/base instead of the outdated /proc/device-tree 2026-01-20 09:11:47 +08:00
Carter Li 927d44d919 Chassis (Linux): uses /proc/device-tree/smbios if available 2026-01-20 08:59:22 +08:00
Carter Li 3b9a91e8af DE (Linux): silences compiler warnings [ci skip] 2026-01-20 08:34:46 +08:00
李通洲 70b4582bb6 DE (Linux): removes option slowVersionDetection
It's always true now

Fixes #2149
2026-01-19 10:55:30 +08:00
李通洲 461552b8d0 DynamicInterval: reruns prepare code before next interval
Fixes #2152
2026-01-16 20:02:03 +08:00
Carter Li 0f3db37199 Chassis (Linux): supports arm devices 2026-01-16 16:47:51 +08:00
Carter Li 67f16b269a DisplayServer (Linux): regenerates wlr-output-management-unstable-v1*
NOOP
2026-01-16 10:40:53 +08:00
李通洲 25671fa4b4 DisplayServer (Linux): fixes crashes on KDE beta
Fixes #2150
2026-01-16 10:13:50 +08:00
Kirill Rekhov 4eaa04d4a4 Presets: update examples to replace deprecated --load-config with --config 2026-01-16 00:43:03 +08:00
李通洲 7592885b9f GPU (Windows): ensures devId is uppercase for consistent parsing 2026-01-15 15:46:21 +08:00
李通洲 508a3fde36 Windows: fixes building 2026-01-15 15:43:05 +08:00
李通洲 f0273224e0 JsonSchema: update [ci skip] 2026-01-15 15:24:54 +08:00
李通洲 31e833c02e Colors: updates module description
Fixes #2147
2026-01-15 15:20:38 +08:00
李通洲 a20d915412 JsonConfig: supports --structure-disabled 2026-01-15 15:11:08 +08:00
李通洲 d3453de73c Global: puts more fastfetch-only properties into FFdata 2026-01-15 15:06:23 +08:00
李通洲 79a11c4728 CommandOption: adds a new option --structure-disabled (WIP)
To disable modules temporarily
2026-01-15 10:35:21 +08:00
李通洲 24591417ce FFstrbuf: clarify usage requirements for ffStrbufGetdelim and friends 2026-01-15 10:30:40 +08:00
李通洲 de6d066fc9 LICENSE: update copyright year to 2026 [ci skip] 2026-01-14 16:33:51 +08:00
Carter Li 6362c896f8 Packaging: updates debian stuff [ci skip] 2026-01-14 14:10:46 +08:00
51 changed files with 483 additions and 305 deletions
+22
View File
@@ -1,3 +1,25 @@
# 2.58.0
An early release to fix compatibility issues with KDE Plasma 6.6.
Breaking changes:
* The `de.slowVersionDetection` option has been removed. Slow version detection is now always enabled, as required on non-FHS-compliant distros (e.g., NixOS). (#2149, DE, Linux)
Features:
* Adds the `--structure-disabled <modules...>` command-line flag to temporarily disable module structure printing.
* For example: `fastfetch --structure-disabled colors` removes the color blocks from the default output.
* Supports chassis type detection on Linux ARM devices when reported via the device tree (Chassis, Linux)
* Supports Bedrock Linux version detection (#2155, OS, Linux)
* Honors the `DBPath` and `RootDir` settings in `pacman.conf` when detecting Pacman packages (#2154, Packages, Linux)
Bugfixes:
* Fixes a crash issues on KDE Plasma 6.6 (Display, Linux)
* Fixes the Command module not working with `--dynamic-interval` (#2152, Command)
* Fixes Quartz Compositor version detection. It now correctly reports the version of `WindowServer` (`SkyLight`) instead of `WindowManager`. (WM, macOS)
Logos:
* Adds Kiss2
# 2.57.1
Features:
+1 -1
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.57.1
VERSION 2.58.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
+1 -1
View File
@@ -1,7 +1,7 @@
MIT License
Copyright (c) 2021-2023 Linus Dierheimer
Copyright (c) 2022-2025 Carter Li
Copyright (c) 2022-2026 Carter Li
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+6
View File
@@ -1,3 +1,9 @@
fastfetch (2.57.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.57.1
-- Carter Li <zhangsongcui@live.cn> Wed, 14 Jan 2026 14:00:17 +0800
fastfetch (2.57.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.57.0
+1 -1
View File
@@ -1999,7 +1999,7 @@
"additionalProperties": false,
"properties": {
"type": {
"description": "Print some colored blocks",
"description": "Display the terminal's 16-color palette",
"const": "colors"
},
"symbol": {
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/3.jsonc
// Load with --config examples/3.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/4.jsonc
// Load with --config examples/4.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/5.jsonc
// Load with --config examples/5.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+1 -1
View File
@@ -18,7 +18,7 @@ typedef struct FFPlatform
FFstrbuf cacheDir; // Trailing slash included
FFlist configDirs; // List of FFstrbuf, trailing slash included
FFlist dataDirs; // List of FFstrbuf, trailing slash included
FFstrbuf exePath; // The real path of current exe
FFstrbuf exePath; // The real path of current exe (empty if unavailable)
FFstrbuf userName;
FFstrbuf fullUserName;
+12 -4
View File
@@ -103,6 +103,10 @@ FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultV
void ffStrbufUpperCase(FFstrbuf* strbuf);
void ffStrbufLowerCase(FFstrbuf* strbuf);
// Function alters the buffer to extract lines or delimited segments (replaces the delimiter with '\0')
// so that buffer MUST be heap allocated (NOT a static string)
// `lineptr` must be `NULL` and `n` MUST be `0` for the first call
// Caller MUST NOT free `*lineptr`
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
@@ -111,10 +115,14 @@ void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf
*
* @details Behaves like getline(3) but reads from a FFstrbuf.
*
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line.
* Can be NULL for the first call.
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line
(points to buffer's internal memory address to avoid memory allocation and copy).
MUST NOT be freed by the caller, unlike `getline(3)`.
* MUST be NULL for the first call.
* @param[in,out] n The pointer to the size of the buffer of lineptr.
* @param[in] buffer The buffer to read from. The buffer must not be a string literal.
MUST be 0 for the first call.
* @param[in] buffer The buffer to read from.
MUST be heap allocated (NOT a static string).
*
* @return true if a line has been read, false if the end of the buffer has been reached.
*/
@@ -124,7 +132,7 @@ static inline bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
}
/**
* @brief Restore the end of a line that was modified by ffStrbufGetline.
* @warning This function should be called before breaking an ffStrbufGetline loop.
* @warning This function should be called before breaking an ffStrbufGetline loop if `buffer` will be used later.
*/
static inline void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
{
+3 -10
View File
@@ -1,15 +1,8 @@
#pragma once
#include "fastfetch.h"
// Things only needed by fastfetch
typedef struct FFdata
{
FFstrbuf structure;
bool configLoaded;
} FFdata;
#include "common/ffdata.h"
void ffPrepareCommandOption(FFdata* data);
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
void ffPrintCommandOption(FFdata* data);
void ffMigrateCommandOptionToJsonc(FFdata* data);
bool ffParseModuleOptions(const char* key, const char* value);
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "common/FFstrbuf.h"
typedef enum __attribute__((__packed__)) FFDataResultDocType
{
FF_RESULT_DOC_TYPE_DEFAULT = 0,
FF_RESULT_DOC_TYPE_JSON,
FF_RESULT_DOC_TYPE_CONFIG,
FF_RESULT_DOC_TYPE_CONFIG_FULL,
} FFDataResultDocType;
// FFdata aggregates configuration, generation parameters, and output state used by fastfetch.
// It holds the parsed configuration document, a mutable JSON document for results, and related metadata.
typedef struct FFdata
{
yyjson_doc* configDoc; // Parsed JSON configuration document
yyjson_mut_doc* resultDoc; // Mutable JSON document for storing results
FFstrbuf structure; // Custom output structure from command line
FFstrbuf structureDisabled; // Disabled modules in the output structure from command line
FFstrbuf genConfigPath; // Path to generate configuration file
FFDataResultDocType docType; // Type of result document
bool configLoaded;
} FFdata;
+78 -53
View File
@@ -71,40 +71,66 @@ bool ffParseModuleOptions(const char* key, const char* value)
void ffPrepareCommandOption(FFdata* data)
{
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME, ':'))
ffPrepareCPUUsage();
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME, ':'))
char* moduleType = NULL;
size_t moduleLen = 0;
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure))
{
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
ffInitDiskIOOptions(&options);
ffPrepareDiskIO(&options);
}
#define FF_IF_MODULE_MATCH(moduleNameConstant) if (moduleLen == strlen(moduleNameConstant) \
&& ffStrEqualsIgnCase(moduleType, moduleNameConstant) \
&& !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':'))
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME, ':'))
{
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
ffInitNetIOOptions(&options);
ffPrepareNetIO(&options);
}
switch (moduleType[0])
{
case 'C': case 'c':
FF_IF_MODULE_MATCH(FF_CPUUSAGE_MODULE_NAME)
ffPrepareCPUUsage();
break;
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME, ':'))
{
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
ffInitPublicIpOptions(&options);
ffPreparePublicIp(&options);
}
case 'D': case 'd':
FF_IF_MODULE_MATCH(FF_DISKIO_MODULE_NAME)
{
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
ffInitDiskIOOptions(&options);
ffPrepareDiskIO(&options);
}
break;
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME, ':'))
{
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
ffInitWeatherOptions(&options);
ffPrepareWeather(&options);
case 'N': case 'n':
FF_IF_MODULE_MATCH(FF_NETIO_MODULE_NAME)
{
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
ffInitNetIOOptions(&options);
ffPrepareNetIO(&options);
}
break;
case 'P': case 'p':
FF_IF_MODULE_MATCH(FF_PUBLICIP_MODULE_NAME)
{
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
ffInitPublicIpOptions(&options);
ffPreparePublicIp(&options);
}
break;
case 'W': case 'w':
FF_IF_MODULE_MATCH(FF_WEATHER_MODULE_NAME)
{
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
ffInitWeatherOptions(&options);
ffPrepareWeather(&options);
}
break;
}
#undef FF_IF_MODULE_MATCH
}
}
static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
static void genJsonConfig(FFdata* data, FFModuleBaseInfo* baseInfo, void* options)
{
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
if (!modules)
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
@@ -112,7 +138,7 @@ static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&type);
if (instance.state.fullConfig)
if (data->docType == FF_RESULT_DOC_TYPE_CONFIG_FULL)
{
yyjson_mut_val* module = yyjson_mut_obj(doc);
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
@@ -131,8 +157,9 @@ static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
}
}
static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
static void genJsonResult(FFdata* data, FFModuleBaseInfo* baseInfo, void* options)
{
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJsonResult)
@@ -142,9 +169,9 @@ static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
}
static void parseStructureCommand(
FFdata* data,
const char* line,
void (*fn)(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* jsonDoc),
yyjson_mut_doc* jsonDoc
void (*fn)(FFdata*, FFModuleBaseInfo* baseInfo, void* options)
)
{
if(ffCharIsEnglishAlphabet(line[0]))
@@ -156,8 +183,8 @@ static void parseStructureCommand(
{
uint8_t optionBuf[FF_OPTION_MAX_SIZE];
baseInfo->initOptions(optionBuf);
if (__builtin_expect(jsonDoc != NULL, false))
fn(baseInfo, optionBuf, jsonDoc);
if (__builtin_expect(data->resultDoc != NULL, false))
fn(data, baseInfo, optionBuf);
else
baseInfo->printModule(optionBuf);
baseInfo->destroyOptions(optionBuf);
@@ -169,30 +196,32 @@ static void parseStructureCommand(
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
}
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
void ffPrintCommandOption(FFdata* data)
{
//Parse the structure and call the modules
int32_t thres = instance.config.display.stat;
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
char* moduleType = NULL;
size_t moduleLen = 0;
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure))
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':'))
continue;
double ms = 0;
if(thres >= 0)
ms = ffTimeGetTick();
parseStructureCommand(data->structure.chars + startIndex, genJsonResult, jsonDoc);
parseStructureCommand(data, moduleType, genJsonResult);
if(thres >= 0)
{
ms = ffTimeGetTick() - ms;
if (jsonDoc)
if (data->resultDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(data->resultDoc->root);
yyjson_mut_obj_add_real(data->resultDoc, moduleJson, "stat", ms);
}
else
{
@@ -205,28 +234,24 @@ void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
}
#if defined(_WIN32)
if (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
if (!data->resultDoc && !instance.config.display.noBuffer) fflush(stdout);
#endif
startIndex = colonIndex + 1;
}
}
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
void ffMigrateCommandOptionToJsonc(FFdata* data)
{
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
char* moduleType = NULL;
size_t moduleLen = 0;
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure))
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':'))
continue;
parseStructureCommand(data->structure.chars + startIndex, genJsonConfig, jsonDoc);
startIndex = colonIndex + 1;
parseStructureCommand(data, moduleType, genJsonConfig);
}
}
+3 -10
View File
@@ -28,8 +28,6 @@ static void initState(FFstate* state)
state->titleFqdn = false;
ffPlatformInit(&state->platform);
state->configDoc = NULL;
state->resultDoc = NULL;
state->dynamicInterval = 0;
{
@@ -96,8 +94,8 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
void ffStart(void)
{
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc;
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe;
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe;
#ifdef _WIN32
SetErrorMode(SEM_FAILCRITICALERRORS);
@@ -124,7 +122,7 @@ void ffStart(void)
#endif
//reset everything to default before we start printing
if(!instance.config.display.pipe && !instance.state.resultDoc)
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(ffHideCursor)
@@ -138,8 +136,6 @@ void ffStart(void)
fputs("\033[?1049h\033[H", stdout); // Enable alternate buffer
fflush(stdout);
}
ffLogoPrint();
}
void ffFinish(void)
@@ -157,9 +153,6 @@ static void destroyConfig(void)
static void destroyState(void)
{
ffPlatformDestroy(&instance.state.platform);
yyjson_doc_free(instance.state.configDoc);
yyjson_mut_doc_free(instance.state.resultDoc);
ffStrbufDestroy(&instance.state.genConfigPath);
}
void ffDestroyInstance(void)
+9 -4
View File
@@ -230,9 +230,10 @@ static bool matchesJsonArray(const char* str, yyjson_val* val)
return false;
}
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
static const char* printJsonConfig(FFdata* data, bool prepare)
{
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
yyjson_mut_doc* jsonDoc = data->resultDoc;
yyjson_val* const root = yyjson_doc_get_root(data->configDoc);
assert(root);
if (!yyjson_is_obj(root))
@@ -298,6 +299,9 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
else
return "modules must be an array of strings or objects";
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, type, ':'))
continue;
if(prepare)
prepareModuleJsonObject(type, module);
else
@@ -329,9 +333,10 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
return NULL;
}
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
void ffPrintJsonConfig(FFdata* data, bool prepare)
{
const char* error = printJsonConfig(prepare, jsonDoc);
yyjson_mut_doc* jsonDoc = data->resultDoc;
const char* error = printJsonConfig(data, prepare);
if (error)
{
if (jsonDoc)
+5 -3
View File
@@ -1,11 +1,10 @@
#pragma once
#include "fastfetch.h"
#include "common/ffdata.h"
#include "common/option.h"
bool ffJsonConfigParseModuleArgs(yyjson_val* key, yyjson_val* val, FFModuleArgs* moduleArgs);
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc);
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* moduleArgs);
yyjson_api_inline yyjson_mut_val* yyjson_mut_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) {
return yyjson_mut_strncpy(doc, buf->chars, buf->length);
@@ -23,3 +22,6 @@ yyjson_api_inline bool yyjson_mut_arr_add_strbuf(yyjson_mut_doc *doc,
const FFstrbuf* buf) {
return yyjson_mut_arr_add_strncpy(doc, obj, buf->chars, buf->length);
}
void ffPrintJsonConfig(FFdata* data, bool prepare);
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* moduleArgs);
+8
View File
@@ -468,6 +468,14 @@
"default": "\"fastfetch --print-structure\""
}
},
{
"long": "structure-disabled",
"desc": "Disable specific modules in the structure",
"remark": "Must be a colon-separated list of keys",
"arg": {
"type": "structure"
}
},
{
"long": "stat",
"desc": "Show time usage (in ms) for individual modules",
+8 -4
View File
@@ -2,8 +2,6 @@
#include "common/io.h"
#include "common/smbiosHelper.h"
#include <stdlib.h>
const char* ffDetectBoard(FFBoardResult* board)
{
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name))
@@ -12,11 +10,17 @@ const char* ffDetectBoard(FFBoardResult* board)
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
}
else if (ffReadFileBuffer("/proc/device-tree/board", &board->name))
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/baseboard/product", &board->name))
{
ffStrbufTrimRight(&board->name, '\0');
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/baseboard/manufacturer", &board->vendor))
ffStrbufTrimRight(&board->vendor, '\0');
}
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/board", &board->name))
{
ffStrbufTrimRightSpace(&board->name);
}
else if (ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor))
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/compatible", &board->vendor))
{
uint32_t comma = ffStrbufFirstIndexC(&board->vendor, ',');
if (comma < board->vendor.length)
+32 -10
View File
@@ -2,20 +2,42 @@
#include "common/io.h"
#include "common/smbiosHelper.h"
#include <stdlib.h>
#include <ctype.h>
const char* ffDetectChassis(FFChassisResult* result)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version);
if(result->type.length)
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type))
{
const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999));
if(typeStr)
ffStrbufSetS(&result->type, typeStr);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version);
if(result->type.length)
{
const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999));
if(typeStr)
ffStrbufSetStatic(&result->type, typeStr);
}
}
else
{
// Available on Asahi Linux
uint32_t chassisType = 0;
if (ffReadFileData("/sys/firmware/devicetree/base/smbios/smbios/chassis/chassis-type", sizeof(chassisType), &chassisType)) // big endian
{
chassisType = __builtin_bswap32(chassisType);
const char* typeStr = ffChassisTypeToString(chassisType);
if(typeStr)
ffStrbufSetStatic(&result->type, typeStr);
if(ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/chassis/manufacturer", &result->vendor) && result->vendor.length > 0)
ffStrbufTrimRight(&result->vendor, '\0');
}
else if(ffReadFileBuffer("/sys/firmware/devicetree/base/chassis-type", &result->type) && result->type.length > 0)
{
ffStrbufTrimRight(&result->type, '\0');
result->type.chars[0] = (char) toupper(result->type.chars[0]);
}
}
return NULL;
}
+1 -1
View File
@@ -741,7 +741,7 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu)
// [x-vendor,x-model\0]*N
char content[512];
ssize_t length = ffReadFileData("/proc/device-tree/compatible", ARRAY_SIZE(content), content);
ssize_t length = ffReadFileData("/sys/firmware/devicetree/base/compatible", ARRAY_SIZE(content), content);
if (length < 4) return; // v,m\0
if (content[length - 1] != '\0') return; // must end with \0
+2 -1
View File
@@ -9,7 +9,8 @@ static uint64_t startTime;
void ffPrepareCPUUsage(void)
{
assert(cpuTimes1.elementSize == 0);
if (cpuTimes1.elementSize != 0) return; // Already prepared
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
ffGetCpuUsageInfo(&cpuTimes1);
startTime = ffTimeGetNow();
+17 -19
View File
@@ -22,7 +22,7 @@
#define _PATH_LOCALBASE "/usr/pkg"
#endif
static void getKDE(FFstrbuf* result, FFDEOptions* options)
static void getKDE(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
#ifdef _PATH_LOCALBASE
ffParsePropFile(_PATH_LOCALBASE "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
@@ -44,7 +44,7 @@ static void getKDE(FFstrbuf* result, FFDEOptions* options)
if(result->length == 0)
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", result);
if(result->length == 0 && options->slowVersionDetection)
if(result->length == 0)
{
if (ffProcessAppendStdOut(result, (char* const[]){
"plasmashell",
@@ -73,7 +73,7 @@ static void getGnome(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
getGnomeByDbus(result);
if (result->length == 0 && options->slowVersionDetection)
if (result->length == 0)
{
if (ffProcessAppendStdOut(result, (char* const[]){
"gnome-shell",
@@ -91,7 +91,7 @@ static void getCinnamon(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
if (result->length == 0)
ffParsePropFileData("applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", result);
if (result->length == 0 && options->slowVersionDetection)
if (result->length == 0)
{
if (ffProcessAppendStdOut(result, (char* const[]){
"cinnamon",
@@ -102,7 +102,7 @@ static void getCinnamon(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
}
}
static void getMate(FFstrbuf* result, FFDEOptions* options)
static void getMate(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
FF_STRBUF_AUTO_DESTROY major = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY minor = ffStrbufCreate();
@@ -116,7 +116,7 @@ static void getMate(FFstrbuf* result, FFDEOptions* options)
ffParseSemver(result, &major, &minor, &micro);
if(result->length == 0 && options->slowVersionDetection)
if(result->length == 0)
{
ffProcessAppendStdOut(result, (char* const[]){
"mate-session",
@@ -143,11 +143,11 @@ static const char* getXfce4ByLib(FFstrbuf* result)
#endif
}
static void getXFCE4(FFstrbuf* result, FFDEOptions* options)
static void getXFCE4(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
getXfce4ByLib(result);
if(result->length == 0 && options->slowVersionDetection)
if(result->length == 0)
{
//This is somewhat slow
ffProcessAppendStdOut(result, (char* const[]){
@@ -162,7 +162,7 @@ static void getXFCE4(FFstrbuf* result, FFDEOptions* options)
}
}
static void getLXQt(FFstrbuf* result, FFDEOptions* options)
static void getLXQt(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
ffParsePropFileData("gconfig/lxqt.pc", "Version:", result);
@@ -171,7 +171,7 @@ static void getLXQt(FFstrbuf* result, FFDEOptions* options)
if(result->length == 0)
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", result);
if(result->length == 0 && options->slowVersionDetection)
if(result->length == 0)
{
//This is really, really, really slow. Thank you, LXQt developers
ffProcessAppendStdOut(result, (char* const[]){
@@ -206,7 +206,7 @@ static bool extractTdeVersion(const char* line, uint32_t len, void *userdata)
return false;
}
static const char* getTrinity(FFstrbuf* result, FFDEOptions* options)
static const char* getTrinity(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("tde-config", &path);
@@ -218,15 +218,13 @@ static const char* getTrinity(FFstrbuf* result, FFDEOptions* options)
if (ffBinaryExtractStrings(path.chars, extractTdeVersion, result, strlen("R0.0.0")) == NULL)
return NULL;
if (options->slowVersionDetection)
ffStrbufClear(&path);
if (ffProcessAppendStdOut(&path, (char* const[]){
"tde-config",
"--version",
NULL
}) == NULL)
{
ffStrbufClear(&path);
ffProcessAppendStdOut(&path, (char* const[]){
"tde-config",
"--version",
NULL
});
ffParsePropLines(path.chars , "TDE: ", result);
return NULL;
}
+2
View File
@@ -11,6 +11,8 @@ void ffPrepareDiskIO(FFDiskIOOptions* options)
{
if (options->detectTotal) return;
if (time1 != 0) return; // Already prepared
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
ffDiskIOGetIoCounters(&ioCounters1, options);
time1 = ffTimeGetNow();
@@ -39,6 +39,7 @@ static const struct kde_output_device_mode_v2_listener modeListener = {
.refresh = waylandKdeModeRefreshListener,
.preferred = waylandKdeModePreferredListener,
.removed = (void*) stubListener,
.flags = (void*) stubListener,
};
static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, struct kde_output_device_mode_v2 *mode)
@@ -1,4 +1,4 @@
/* Generated by wayland-scanner 1.22.0 */
/* Generated by wayland-scanner 1.24.0 */
#ifndef WLR_OUTPUT_MANAGEMENT_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define WLR_OUTPUT_MANAGEMENT_UNSTABLE_V1_CLIENT_PROTOCOL_H
@@ -445,9 +445,8 @@ struct zwlr_output_head_v1_listener {
* However, do not assume that the name is a reflection of an
* underlying DRM connector, X11 connection, etc.
*
* If the compositor implements the xdg-output protocol and this
* head is enabled, the xdg_output.name event must report the same
* name.
* If this head matches a wl_output, the wl_output.name event must
* report the same name.
*
* The name event is sent after a wlr_output_head object is
* created. This event is only sent once per object, and the name
@@ -468,9 +467,8 @@ struct zwlr_output_head_v1_listener {
* underlying DRM connector or the display name of the underlying
* X11 connection, etc.
*
* If the compositor implements xdg-output and this head is
* enabled, the xdg_output.description must report the same
* description.
* If this head matches a wl_output, the wl_output.description
* event must report the same name.
*
* The description event is sent after a wlr_output_head object is
* created. This event is only sent once per object, and the
@@ -486,6 +484,11 @@ struct zwlr_output_head_v1_listener {
* This event describes the physical size of the head. This event
* is only sent if the head has a physical size (e.g. is not a
* projector or a virtual device).
*
* The physical size event is sent after a wlr_output_head object
* is created. This event is only sent once per object, and the
* physical size does not change over the lifetime of the
* wlr_output_head object.
* @param width width in millimeters of the output
* @param height height in millimeters of the output
*/
@@ -568,9 +571,6 @@ struct zwlr_output_head_v1_listener {
*
* This event describes the manufacturer of the head.
*
* This must report the same make as the wl_output interface does
* in its geometry event.
*
* Together with the model and serial_number events the purpose is
* to allow clients to recognize heads from previous sessions and
* for example load head-specific configurations back.
@@ -583,6 +583,10 @@ struct zwlr_output_head_v1_listener {
* other events but should be aware that there is an increased risk
* of false positives.
*
* If sent, the make event is sent after a wlr_output_head object
* is created and only sent once per object. The make does not
* change over the lifetime of the wlr_output_head object.
*
* It is not recommended to display the make string in UI to users.
* For that the string provided by the description event should be
* preferred.
@@ -596,9 +600,6 @@ struct zwlr_output_head_v1_listener {
*
* This event describes the model of the head.
*
* This must report the same model as the wl_output interface does
* in its geometry event.
*
* Together with the make and serial_number events the purpose is
* to allow clients to recognize heads from previous sessions and
* for example load head-specific configurations back.
@@ -611,6 +612,10 @@ struct zwlr_output_head_v1_listener {
* information from other events but should be aware that there is
* an increased risk of false positives.
*
* If sent, the model event is sent after a wlr_output_head object
* is created and only sent once per object. The model does not
* change over the lifetime of the wlr_output_head object.
*
* It is not recommended to display the model string in UI to
* users. For that the string provided by the description event
* should be preferred.
@@ -636,6 +641,11 @@ struct zwlr_output_head_v1_listener {
* events but should be aware that there is an increased risk of
* false positives.
*
* If sent, the serial number event is sent after a wlr_output_head
* object is created and only sent once per object. The serial
* number does not change over the lifetime of the wlr_output_head
* object.
*
* It is not recommended to display the serial_number string in UI
* to users. For that the string provided by the description event
* should be preferred.
@@ -1,6 +1,6 @@
#ifdef FF_HAVE_WAYLAND
/* Generated by wayland-scanner 1.22.0 */
/* Generated by wayland-scanner 1.24.0 */
/*
* Copyright © 2019 Purism SPC
@@ -27,6 +27,7 @@
* THIS SOFTWARE.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
+7 -4
View File
@@ -54,6 +54,12 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
}
FF_DEBUG("Device instance ID: %lu", devInst);
for (wchar_t* p = devId; *p; p++)
{
if (*p >= L'a' && *p <= L'z')
*p -= L'a' - L'A';
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
deviceCount++;
FF_DEBUG("Added GPU #%d to list", deviceCount);
@@ -73,10 +79,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
if (
(*devId == 'P' && swscanf(devId, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) ||
(*devId == 'p' && swscanf(devId, L"pci\\ven_%x&dev_%x&subsys_%x&rev_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) // Windows 7
)
if (swscanf(devId, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4)
{
FF_DEBUG("Parsed PCI IDs - Vendor: 0x%x, Device: 0x%x, SubSystem: 0x%x, Rev: 0x%x", vendorId, deviceId, subSystemId, revId);
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
+12 -17
View File
@@ -9,18 +9,14 @@ static void getHostProductName(FFstrbuf* name)
{
if (ffReadFileBuffer("/sys/firmware/devicetree/base/model", name))
{
ffStrbufTrimRightSpace(name);
ffStrbufTrimRight(name, '\0');
if(ffIsSmbiosValueSet(name))
return;
return;
}
if (ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name))
{
ffStrbufTrimRightSpace(name);
ffStrbufTrimRight(name, '\0');
if(ffIsSmbiosValueSet(name))
return;
return;
}
if (ffReadFileBuffer("/tmp/sysinfo/model", name))
@@ -36,20 +32,19 @@ static void getHostProductName(FFstrbuf* name)
static void getHostSerialNumber(FFstrbuf* serial)
{
if (ffReadFileBuffer("/sys/firmware/devicetree/base/serial-number", serial))
{
ffStrbufTrimRightSpace(serial);
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/serial", serial))
ffStrbufTrimRight(serial, '\0');
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/serial-number", serial))
ffStrbufTrimRight(serial, '\0');
if(ffIsSmbiosValueSet(serial))
return;
}
ffStrbufClear(serial);
}
const char* ffDetectHost(FFHostResult* host)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->family);
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->family))
{
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/product", &host->family))
ffStrbufTrimRight(&host->family, '\0');
}
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &host->name))
getHostProductName(&host->name);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->version);
@@ -59,8 +54,8 @@ const char* ffDetectHost(FFHostResult* host)
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_uuid", "/sys/class/dmi/id/product_uuid", &host->uuid);
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->vendor))
{
if (ffStrbufStartsWithS(&host->name, "Apple "))
ffStrbufSetStatic(&host->vendor, "Apple Inc.");
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/manufacturer", &host->vendor))
ffStrbufTrimRight(&host->vendor, '\0');
}
#ifdef __x86_64__
+2
View File
@@ -9,6 +9,8 @@ void ffPrepareNetIO(FFNetIOOptions* options)
{
if (options->detectTotal) return;
if (time1 != 0) return; // Already prepared
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
ffNetIOGetIoCounters(&ioCounters1, options);
time1 = ffTimeGetNow();
+1 -15
View File
@@ -313,21 +313,7 @@ static bool detectBedrock(FFOSResult* os)
{
const char* bedrockRestrict = getenv("BEDROCK_RESTRICT");
if(bedrockRestrict && bedrockRestrict[0] == '1') return false;
if(parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os))
{
if(os->id.length == 0)
ffStrbufAppendS(&os->id, "bedrock");
if(os->name.length == 0)
ffStrbufAppendS(&os->name, "Bedrock");
if(os->prettyName.length == 0)
ffStrbufAppendS(&os->prettyName, "Bedrock Linux");
parseOsRelease("/bedrock" FASTFETCH_TARGET_DIR_ETC "/os-release", os);
return true;
}
return false;
return parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock/strata/bedrock/etc/os-release", os);
}
static void detectOS(FFOSResult* os)
+40 -1
View File
@@ -412,6 +412,45 @@ static uint32_t getFlatpakPackages(FFstrbuf* baseDir, const char* dirname)
return num_elements;
}
static uint32_t getPacmanPackages(FFstrbuf* baseDir)
{
FF_STRBUF_AUTO_DESTROY dbPath = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY rootDir = ffStrbufCreate();
// Get path to pacman.conf
uint32_t baseDirLen = baseDir->length;
ffStrbufAppendS(baseDir, "/etc/pacman.conf");
bool confFound = ffParsePropFileValues(baseDir->chars, 2, (FFpropquery[]){
{ "DBPath =", &dbPath },
{ "RootDir =", &rootDir },
});
ffStrbufSubstrBefore(baseDir, baseDirLen);
if (confFound)
{
if (dbPath.length > 0)
{
// If DBPath is specified, use it
ffStrbufEnsureEndsWithC(&dbPath, '/');
ffStrbufAppendS(&dbPath, "local");
}
else if (rootDir.length > 0)
{
// ... otherwise, use RootDir
ffStrbufDestroy(&dbPath);
ffStrbufInitMove(&dbPath, &rootDir);
ffStrbufEnsureEndsWithC(&dbPath, '/');
ffStrbufAppendS(&dbPath, "var/lib/pacman/local");
}
}
if (dbPath.length == 0)
ffStrbufSetStatic(&dbPath, "/var/lib/pacman/local");
return getNumElements(baseDir, dbPath.chars, true);
}
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q", "apk");
@@ -426,7 +465,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
packageCounts->nixDefault += ffPackagesGetNix(baseDir, "/nix/var/nix/profiles/default");
packageCounts->nixSystem += ffPackagesGetNix(baseDir, "/run/current-system");
}
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", true);
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getPacmanPackages(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_LPKGBUILD_BIT)) packageCounts->lpkgbuild += getNumElements(baseDir, "/opt/Loc-OS-LPKG/lpkgbuild/remove", false);
if (!(options->disabled & FF_PACKAGES_FLAG_PKGTOOL_BIT)) packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", false);
if (!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT))
+9 -2
View File
@@ -50,9 +50,16 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE
if (ffStrbufEqualS(wmName, "WindowServer"))
{
NSError* error;
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"file:///System/Library/CoreServices/WindowManager.app/Contents/version.plist"]
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"file:///System/Library/PrivateFrameworks/SkyLight.framework/Resources/version.plist"]
error:&error];
ffStrbufInitS(result, ((NSString*) dict[@"CFBundleVersion"]).UTF8String);
if (!dict)
{
dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"file:///System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/version.plist"]
error:&error];
}
if (dict)
ffStrbufInitS(result, ((NSString*) dict[@"CFBundleShortVersionString"]).UTF8String);
}
return NULL;
+81 -64
View File
@@ -1,4 +1,5 @@
#include "fastfetch.h"
#include "common/ffdata.h"
#include "detection/version/version.h"
#include "logo/logo.h"
#include "common/commandoption.h"
@@ -379,16 +380,16 @@ static void listModules(bool pretty)
}
}
static bool parseJsoncFile(const char* path, yyjson_read_flag flg)
static bool parseJsoncFile(FFdata* data, const char* path, yyjson_read_flag flg)
{
assert(!instance.state.configDoc);
assert(!data->configDoc);
{
yyjson_read_err error;
instance.state.configDoc = path
data->configDoc = path
? yyjson_read_file(path, flg, NULL, &error)
: yyjson_read_fp(stdin, flg, NULL, &error);
if (!instance.state.configDoc)
if (!data->configDoc)
{
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
{
@@ -412,7 +413,7 @@ static bool parseJsoncFile(const char* path, yyjson_read_flag flg)
{
const char* error = NULL;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
yyjson_val* const root = yyjson_doc_get_root(data->configDoc);
if (!yyjson_is_obj(root))
error = "Invalid JSON config format. Root value must be an object";
@@ -432,8 +433,14 @@ static bool parseJsoncFile(const char* path, yyjson_read_flag flg)
}
static void generateConfigFile(bool force, const char* filePath, bool fullConfig)
static void generateConfigFile(FFdata* data, bool force, const char* filePath, bool fullConfig)
{
if (data->resultDoc)
{
fprintf(stderr, "Error: duplicated `--gen-config` or `--format json` flags found\n");
exit(477);
}
if (!filePath)
{
if (instance.state.platform.configDirs.length == 0)
@@ -443,22 +450,23 @@ static void generateConfigFile(bool force, const char* filePath, bool fullConfig
}
FFstrbuf* configDir = FF_LIST_FIRST(FFstrbuf, instance.state.platform.configDirs);
ffStrbufEnsureFixedLengthFree(&instance.state.genConfigPath, configDir->length + strlen("fastfetch/config.jsonc"));
ffStrbufSet(&instance.state.genConfigPath, configDir);
ffStrbufAppendS(&instance.state.genConfigPath, "fastfetch/config.jsonc");
ffStrbufEnsureFixedLengthFree(&data->genConfigPath, configDir->length + strlen("fastfetch/config.jsonc"));
ffStrbufSet(&data->genConfigPath, configDir);
ffStrbufAppendS(&data->genConfigPath, "fastfetch/config.jsonc");
}
else
{
ffStrbufSetS(&instance.state.genConfigPath, filePath);
ffStrbufSetS(&data->genConfigPath, filePath);
}
if (!force && ffPathExists(instance.state.genConfigPath.chars, FF_PATHTYPE_ANY))
if (!force && ffPathExists(data->genConfigPath.chars, FF_PATHTYPE_ANY))
{
fprintf(stderr, "Error: file `%s` exists. Use `--gen-config%s-force` to overwrite\n", instance.state.genConfigPath.chars, fullConfig ? "-full" : "");
fprintf(stderr, "Error: file `%s` exists. Use `--gen-config%s-force` to overwrite\n", data->genConfigPath.chars, fullConfig ? "-full" : "");
exit(477);
}
instance.state.fullConfig = fullConfig;
data->docType = fullConfig ? FF_RESULT_DOC_TYPE_CONFIG_FULL : FF_RESULT_DOC_TYPE_CONFIG;
data->resultDoc = yyjson_mut_doc_new(NULL);
}
static void optionParseConfigFile(FFdata* data, const char* key, const char* value)
@@ -482,7 +490,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
if (value[0] == '-' && value[1] == '\0')
{
parseJsoncFile(NULL, false);
parseJsoncFile(data, NULL, false);
return;
}
@@ -503,7 +511,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
? YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS
: YYJSON_READ_JSON5;
if (parseJsoncFile(absolutePath.chars, flag)) return;
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
//Try to load as a relative path with the config directory
@@ -515,7 +523,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
if (needExtension)
ffStrbufAppendS(&absolutePath, ".jsonc");
if (parseJsoncFile(absolutePath.chars, flag)) return;
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
}
//Try to load as a preset
@@ -528,7 +536,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
if (needExtension)
ffStrbufAppendS(&absolutePath, ".jsonc");
if (parseJsoncFile(absolutePath.chars, flag)) return;
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
}
//Try to load as a relative path with the directory of fastfetch binary, for Windows support
@@ -543,7 +551,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
ffStrbufAppendS(&absolutePath, value);
if (needExtension)
ffStrbufAppendS(&absolutePath, ".jsonc");
if (parseJsoncFile(absolutePath.chars, flag)) return;
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
// Try {exePath}/presets/
ffStrbufSubstrBefore(&absolutePath, lastSlash);
@@ -551,7 +559,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
ffStrbufAppendS(&absolutePath, value);
if (needExtension)
ffStrbufAppendS(&absolutePath, ".jsonc");
if (parseJsoncFile(absolutePath.chars, flag)) return;
if (parseJsoncFile(data, absolutePath.chars, flag)) return;
}
//File not found
@@ -566,24 +574,17 @@ static void printVersion()
printf("%s %s%s%s (%s)\n", result->projectName, result->version, result->versionTweak, result->debugMode ? "-debug" : "", result->architecture);
}
static void enableJsonOutput(bool enable)
static void enableJsonOutput(FFdata* data)
{
if (!enable)
if (data->resultDoc)
{
if (instance.state.resultDoc)
{
yyjson_mut_doc_free(instance.state.resultDoc);
instance.state.resultDoc = NULL;
}
}
else
{
if (!instance.state.resultDoc)
{
instance.state.resultDoc = yyjson_mut_doc_new(NULL);
yyjson_mut_doc_set_root(instance.state.resultDoc, yyjson_mut_arr(instance.state.resultDoc));
}
fprintf(stderr, "Error: duplicated `--gen-config` or `--format json` flags found\n");
exit(477);
}
data->resultDoc = yyjson_mut_doc_new(NULL);
data->docType = FF_RESULT_DOC_TYPE_JSON;
yyjson_mut_doc_set_root(data->resultDoc, yyjson_mut_arr(data->resultDoc));
}
static void parseCommand(FFdata* data, char* key, char* value)
@@ -668,24 +669,26 @@ static void parseCommand(FFdata* data, char* key, char* value)
exit(0);
}
else if(ffStrEqualsIgnCase(key, "--gen-config"))
generateConfigFile(false, value, false);
generateConfigFile(data, false, value, false);
else if(ffStrEqualsIgnCase(key, "--gen-config-force"))
generateConfigFile(true, value, false);
generateConfigFile(data, true, value, false);
else if(ffStrEqualsIgnCase(key, "--gen-config-full"))
generateConfigFile(false, value, true);
generateConfigFile(data, false, value, true);
else if(ffStrEqualsIgnCase(key, "--gen-config-full-force"))
generateConfigFile(true, value, true);
generateConfigFile(data, true, value, true);
else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--config"))
optionParseConfigFile(data, key, value);
else if(ffStrEqualsIgnCase(key, "-j") || ffStrEqualsIgnCase(key, "--json"))
enableJsonOutput(ffOptionParseBoolean(value));
{
if (ffOptionParseBoolean(value)) enableJsonOutput(data);
}
else if(ffStrEqualsIgnCase(key, "--format"))
{
enableJsonOutput(!!ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
if (!!ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", false},
{ "json", true },
{},
}));
})) enableJsonOutput(data);
}
else if(ffStrEqualsIgnCase(key, "--dynamic-interval"))
instance.state.dynamicInterval = ffOptionParseUInt32(key, value); // seconds to milliseconds
@@ -710,6 +713,9 @@ static void parseOption(FFdata* data, const char* key, const char* value)
ffParseModuleOptions(key, value)
) {}
else if(ffStrEqualsIgnCase(key, "--structure-disabled"))
ffOptionParseString(key, value, &data->structureDisabled);
else
{
fprintf(stderr, "Error: unknown option: %s\n", key);
@@ -717,21 +723,21 @@ static void parseOption(FFdata* data, const char* key, const char* value)
}
}
static void parseConfigFiles(void)
static void parseConfigFiles(FFdata* data)
{
if (__builtin_expect(instance.state.genConfigPath.length == 0, true))
if (__builtin_expect(data->genConfigPath.length == 0, true))
{
FF_LIST_FOR_EACH(FFstrbuf, dir, instance.state.platform.configDirs)
{
uint32_t dirLength = dir->length;
ffStrbufAppendS(dir, "fastfetch/config.jsonc");
bool success = parseJsoncFile(dir->chars, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS);
bool success = parseJsoncFile(data, dir->chars, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS);
ffStrbufSubstrBefore(dir, dirLength);
if (success) return;
ffStrbufAppendS(dir, "fastfetch/config.json5");
success = parseJsoncFile(dir->chars, YYJSON_READ_JSON5);
success = parseJsoncFile(data, dir->chars, YYJSON_READ_JSON5);
ffStrbufSubstrBefore(dir, dirLength);
if (success) return;
}
@@ -769,10 +775,10 @@ static void parseArguments(FFdata* data, int argc, char** argv, void (*parser)(F
static void run(FFdata* data)
{
const bool useJsonConfig = data->structure.length == 0 && instance.state.configDoc;
const bool useJsonConfig = data->structure.length == 0 && data->configDoc;
if (useJsonConfig)
ffPrintJsonConfig(true /* prepare */, instance.state.resultDoc);
ffPrintJsonConfig(data, true /* prepare */);
else
{
//If we don't have a custom structure, use the default one
@@ -783,6 +789,9 @@ static void run(FFdata* data)
ffStart();
if (!data->resultDoc)
ffLogoPrint();
#if defined(_WIN32)
if (!instance.config.display.noBuffer) fflush(stdout);
#endif
@@ -790,9 +799,9 @@ static void run(FFdata* data)
while (true)
{
if (useJsonConfig)
ffPrintJsonConfig(false, instance.state.resultDoc);
ffPrintJsonConfig(data, false);
else
ffPrintCommandOption(data, instance.state.resultDoc);
ffPrintCommandOption(data);
if (instance.state.dynamicInterval > 0)
{
@@ -802,10 +811,15 @@ static void run(FFdata* data)
}
else
break;
if (useJsonConfig)
ffPrintJsonConfig(data, true /* prepare */);
else
ffPrepareCommandOption(data);
}
if (instance.state.resultDoc)
yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
if (data->resultDoc)
yyjson_mut_write_fp(stdout, data->resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
else
{
if (instance.config.logo.printRemaining)
@@ -816,20 +830,20 @@ static void run(FFdata* data)
static void writeConfigFile(FFdata* data)
{
const FFstrbuf* filename = &instance.state.genConfigPath;
const FFstrbuf* filename = &data->genConfigPath;
yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL);
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
yyjson_mut_obj_add_str(doc, root, "$schema", "https://github.com/fastfetch-cli/fastfetch/raw/master/doc/json_schema.json");
if (instance.state.fullConfig)
if (data->docType == FF_RESULT_DOC_TYPE_CONFIG_FULL)
{
ffOptionsGenerateLogoJsonConfig(&instance.config.logo, doc);
ffOptionsGenerateDisplayJsonConfig(&instance.config.display, doc);
ffOptionsGenerateGeneralJsonConfig(&instance.config.general, doc);
ffOptionsGenerateLogoJsonConfig(data, &instance.config.logo);
ffOptionsGenerateDisplayJsonConfig(data, &instance.config.display);
ffOptionsGenerateGeneralJsonConfig(data, &instance.config.general);
}
ffMigrateCommandOptionToJsonc(data, doc);
ffMigrateCommandOptionToJsonc(data);
if (ffStrbufEqualS(filename, "-"))
yyjson_mut_write_fp(stdout, doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
@@ -854,8 +868,6 @@ static void writeConfigFile(FFdata* data)
exit(1);
}
}
yyjson_mut_doc_free(doc);
}
int main(int argc, char** argv)
@@ -866,24 +878,29 @@ int main(int argc, char** argv)
//Data stores things only needed for the configuration of fastfetch
FFdata data = {
.structure = ffStrbufCreate(),
.configLoaded = false,
.structureDisabled = ffStrbufCreate(),
.genConfigPath = ffStrbufCreate(),
};
parseArguments(&data, argc, argv, parseCommand);
if(instance.state.dynamicInterval && instance.state.resultDoc)
if(instance.state.dynamicInterval && data.resultDoc)
{
fprintf(stderr, "Error: --dynamic-interval cannot be used with --json\n");
exit(400);
}
if(!data.configLoaded && !getenv("NO_CONFIG"))
parseConfigFiles();
parseConfigFiles(&data);
parseArguments(&data, argc, argv, (void*) parseOption);
if (__builtin_expect(instance.state.genConfigPath.length == 0, true))
if (__builtin_expect(data.genConfigPath.length == 0, true))
run(&data);
else
writeConfigFile(&data);
ffStrbufDestroy(&data.structure);
ffStrbufDestroy(&data.structureDisabled);
yyjson_doc_free(data.configDoc);
yyjson_mut_doc_free(data.resultDoc);
ffStrbufDestroy(&data.genConfigPath);
}
+1 -12
View File
@@ -5,12 +5,6 @@
#include <stdint.h>
#include <stdbool.h>
#ifdef FF_USE_SYSTEM_YYJSON
#include <yyjson.h>
#else
#include "3rdparty/yyjson/yyjson.h"
#endif
#ifdef _MSC_VER
#define __attribute__(x)
#endif
@@ -40,13 +34,8 @@ typedef struct FFstate
uint32_t keysHeight;
bool terminalLightTheme;
bool titleFqdn;
FFPlatform platform;
yyjson_doc* configDoc;
yyjson_mut_doc* resultDoc;
FFstrbuf genConfigPath;
bool fullConfig;
uint32_t dynamicInterval;
FFPlatform platform;
} FFstate;
typedef struct FFinstance
+4 -1
View File
@@ -16,9 +16,12 @@ int main(void)
instance.config.display.freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER;
instance.config.display.sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER;
// Logo printing and other preparation stuff
// Some preparation stuff
ffStart();
// Print logo
ffLogoPrint();
// Print all modules
{
__attribute__((cleanup(ffDestroyTitleOptions))) FFTitleOptions options;
+11
View File
@@ -0,0 +1,11 @@
██████ ██████
██$2██████$1████$2██████$1██
██$3████$2████████████████$1██
██$2██$3████$2██████████████████$1██
██$2██$3██$2████$3████████████$2████████$1██
██$2██████$3████████████████$2██████$1██
██$2████████████████████████████$1██
██$2████████████████████████$1██
██$2██████$3████████$2██████$1██
████$2████████████$1████
████████████
+12
View File
@@ -2536,6 +2536,18 @@ static const FFlogo K[] = {
.colorKeys = FF_COLOR_FG_MAGENTA,
.colorTitle = FF_COLOR_FG_BLUE,
},
// KISSLinux2
{
.names = {"kiss2"},
.lines = FASTFETCH_DATATEXT_LOGO_KISS2,
.colors = {
FF_COLOR_FG_BLACK,
FF_COLOR_FG_RED,
FF_COLOR_FG_WHITE,
},
.colorKeys = FF_COLOR_FG_RED,
.colorTitle = FF_COLOR_FG_RED,
},
// Kogaion
{
.names = {"Kogaion"},
+3 -12
View File
@@ -424,7 +424,8 @@ static void logoPrintStruct(const FFlogo* logo)
static void logoPrintNone(void)
{
logoApplyColors(logoGetBuiltinDetected(FF_LOGO_SIZE_NORMAL), false);
if (!instance.config.display.pipe)
logoApplyColors(logoGetBuiltinDetected(FF_LOGO_SIZE_NORMAL), false);
instance.state.logoHeight = 0;
instance.state.logoWidth = 0;
}
@@ -614,16 +615,6 @@ static bool logoTryKnownType(void)
void ffLogoPrint(void)
{
//When generate JSON result, we don't have a logo or padding.
//We also don't need to set main color, because it won't be printed anyway.
//So we can return quickly here.
if(instance.state.resultDoc)
{
instance.state.logoHeight = 0;
instance.state.logoWidth = 0;
return;
}
const FFOptionsLogo* options = &instance.config.logo;
if (options->type == FF_LOGO_TYPE_NONE)
@@ -711,7 +702,7 @@ void ffLogoPrintLine(void)
printf("\033[%uC", instance.state.logoWidth);
if (instance.state.dynamicInterval > 0)
fputs("\033[K", stdout);
fputs("\033[K", stdout); // Clear to the end of the line
++instance.state.keysHeight;
}
+1 -1
View File
@@ -249,7 +249,7 @@ void ffDestroyColorsOptions(FFColorsOptions* options)
FFModuleBaseInfo ffColorsModuleInfo = {
.name = FF_COLORS_MODULE_NAME,
.description = "Print some colored blocks",
.description = "Display the terminal's 16-color palette",
.initOptions = (void*) ffInitColorsOptions,
.destroyOptions = (void*) ffDestroyColorsOptions,
.parseJsonObject = (void*) ffParseColorsJsonObject,
+1 -5
View File
@@ -55,7 +55,7 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module)
if (unsafe_yyjson_equals_str(key, "slowVersionDetection"))
{
options->slowVersionDetection = yyjson_get_bool(val);
ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true");
continue;
}
@@ -66,8 +66,6 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module)
void ffGenerateDEJsonConfig(FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
yyjson_mut_obj_add_bool(doc, module, "slowVersionDetection", options->slowVersionDetection);
}
bool ffGenerateDEJsonResult(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -93,8 +91,6 @@ bool ffGenerateDEJsonResult(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc
void ffInitDEOptions(FFDEOptions* options)
{
ffOptionInitModuleArg(&options->moduleArgs, "");
options->slowVersionDetection = false;
}
void ffDestroyDEOptions(FFDEOptions* options)
-2
View File
@@ -5,8 +5,6 @@
typedef struct FFDEOptions
{
FFModuleArgs moduleArgs;
bool slowVersionDetection;
} FFDEOptions;
static_assert(sizeof(FFDEOptions) <= FF_OPTION_MAX_SIZE, "FFDEOptions size exceeds maximum allowed size");
+2 -1
View File
@@ -909,8 +909,9 @@ void ffOptionsDestroyDisplay(FFOptionsDisplay* options)
ffListDestroy(&options->constants);
}
void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_doc* doc)
void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options)
{
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, doc->root, "display");
if (options->stat <= 0)
+2 -1
View File
@@ -1,5 +1,6 @@
#pragma once
#include "common/ffdata.h"
#include "common/percent.h"
#include "common/FFstrbuf.h"
#include "common/FFlist.h"
@@ -98,4 +99,4 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key, const char* value);
void ffOptionsInitDisplay(FFOptionsDisplay* options);
void ffOptionsDestroyDisplay(FFOptionsDisplay* options);
void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_doc* doc);
void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options);
+2 -1
View File
@@ -117,8 +117,9 @@ void ffOptionsDestroyGeneral(FF_MAYBE_UNUSED FFOptionsGeneral* options)
#endif
}
void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_doc* doc)
void ffOptionsGenerateGeneralJsonConfig(FFdata* data, FFOptionsGeneral* options)
{
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, doc->root, "general");
yyjson_mut_obj_add_bool(doc, obj, "thread", options->multithreading);
+2 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#include "common/FFstrbuf.h"
#include "common/ffdata.h"
typedef enum __attribute__((__packed__)) FFDsForceDrmType
{
@@ -28,4 +28,4 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key, const char* value);
void ffOptionsInitGeneral(FFOptionsGeneral* options);
void ffOptionsDestroyGeneral(FFOptionsGeneral* options);
void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_doc* doc);
void ffOptionsGenerateGeneralJsonConfig(FFdata* data, FFOptionsGeneral* options);
+2 -1
View File
@@ -466,8 +466,9 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
return NULL;
}
void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc)
void ffOptionsGenerateLogoJsonConfig(FFdata* data, FFOptionsLogo* options)
{
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* obj = yyjson_mut_obj(doc);
switch (options->type)
+19 -19
View File
@@ -1,28 +1,28 @@
#pragma once
#include "common/FFstrbuf.h"
#include "common/ffdata.h"
#define FASTFETCH_LOGO_MAX_NAMES 9
#define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9)
#define FASTFETCH_LOGO_MAX_COLORS 9 // two digits would make parsing much more complicated (index 1 - 9)
typedef enum __attribute__((__packed__)) FFLogoType
{
FF_LOGO_TYPE_AUTO, //if something is given, first try builtin, then file. Otherwise detect logo
FF_LOGO_TYPE_BUILTIN, //builtin ascii art
FF_LOGO_TYPE_SMALL, //builtin ascii art, small version
FF_LOGO_TYPE_FILE, //text file, printed with color code replacement
FF_LOGO_TYPE_FILE_RAW, //text file, printed as is
FF_LOGO_TYPE_DATA, //text data, printed with color code replacement
FF_LOGO_TYPE_DATA_RAW, //text data, printed as is
FF_LOGO_TYPE_COMMAND_RAW, //command to generate text data, printed as is
FF_LOGO_TYPE_IMAGE_SIXEL, //image file, printed as sixel codes
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
FF_LOGO_TYPE_IMAGE_KITTY_DIRECT, //image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)
FF_LOGO_TYPE_IMAGE_KITTY_ICAT, //image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed"
FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol
FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa
FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string
FF_LOGO_TYPE_NONE, //--logo none
FF_LOGO_TYPE_AUTO, // if something is given, first try builtin, then file. Otherwise detect logo
FF_LOGO_TYPE_BUILTIN, // builtin ascii art
FF_LOGO_TYPE_SMALL, // builtin ascii art, small version
FF_LOGO_TYPE_FILE, // text file, printed with color code replacement
FF_LOGO_TYPE_FILE_RAW, // text file, printed as is
FF_LOGO_TYPE_DATA, // text data, printed with color code replacement
FF_LOGO_TYPE_DATA_RAW, // text data, printed as is
FF_LOGO_TYPE_COMMAND_RAW, // command to generate text data, printed as is
FF_LOGO_TYPE_IMAGE_SIXEL, // image file, printed as sixel codes
FF_LOGO_TYPE_IMAGE_KITTY, // image file, printed as kitty graphics protocol
FF_LOGO_TYPE_IMAGE_KITTY_DIRECT, // image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)
FF_LOGO_TYPE_IMAGE_KITTY_ICAT, // image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed"
FF_LOGO_TYPE_IMAGE_ITERM, // image file, printed as iterm graphics protocol
FF_LOGO_TYPE_IMAGE_CHAFA, // image file, printed as ascii art using libchafa
FF_LOGO_TYPE_IMAGE_RAW, // image file, printed as raw binary string
FF_LOGO_TYPE_NONE, // `--logo none`, but still applies colors to the system information output (unless `--pipe` is set)
} FFLogoType;
typedef enum __attribute__((__packed__)) FFLogoPosition
@@ -58,4 +58,4 @@ void ffOptionsInitLogo(FFOptionsLogo* options);
bool ffOptionsParseLogoCommandLine(FFOptionsLogo* options, const char* key, const char* value);
void ffOptionsDestroyLogo(FFOptionsLogo* options);
const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* root);
void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc);
void ffOptionsGenerateLogoJsonConfig(FFdata* data, FFOptionsLogo* options);