mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
@@ -59,6 +59,10 @@ strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
|
||||
|
||||
If you cannot do the instructions above, please upload the core dump file:
|
||||
|
||||
## If fastfetch is slow
|
||||
|
||||
Use `time fastfetch --stat` to show time usage for each module.
|
||||
|
||||
## If my image logo didn't show / work
|
||||
|
||||
<!-- Please make sure the terminal does support the image protocol you used. Note Gnome terminal doesn't support any image protocols -->
|
||||
|
||||
+9
-2
@@ -1,4 +1,4 @@
|
||||
# 2.10.3
|
||||
# 2.11.0
|
||||
|
||||
Changes:
|
||||
* Default `hideCursor` to false. It doesn't make much difference but makes user's terminal unusable if fastfetch is not exited correctly.
|
||||
@@ -10,14 +10,21 @@ Bugfixes:
|
||||
* Fix wifi detection on platforms that don't use NetworkManager (#811, Wifi, Linux)
|
||||
* Fix NixOS wrapped process name (#814, Terminal, Linux)
|
||||
* Fix GPU type detection for AMD cards (#816, GPU, Linux)
|
||||
* Silence system deprecation warnings (#822, Camera, macOS)
|
||||
|
||||
Features:
|
||||
* Add basic support DE detection support for UKUI (DE, Linux)
|
||||
* Support printing total number of nix / flatpak / brew packages (Packages)
|
||||
* See `fastfetch -h packages-format` for detail
|
||||
* Better max CPU frequency detection support with `CPUID / 16H` instruction (CPU, Windows)
|
||||
* This requires Core I Gen 6 or newer, and with `Virtual Machine Platform` Windows feature disabled. X86 only.
|
||||
* This requires Intel Core I Gen 6 or newer, and with `Virtual Machine Platform` Windows feature disabled. X86 only.
|
||||
* Improve performance of nix packages detection (Packages, Linux)
|
||||
* Make config specified in JSONC overridable by command line flags
|
||||
* Note this change only make global config overridable; module configs are still not
|
||||
* Suggest increasing `--processing-timeout` when child process timeouts
|
||||
* Only detect folders that specified by `--disk-folders`
|
||||
* Previously `--disk-folders` only omits unmatched disks from output
|
||||
* This option can be used to improve detection performance by ignoring slow network drives
|
||||
|
||||
# 2.10.2
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.10.3
|
||||
VERSION 2.11.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
|
||||
@@ -68,7 +68,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout";
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
{
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "WaitForSingleObject(hChildPipeRead) failed or timeout";
|
||||
return "WaitForSingleObject(hChildPipeRead) failed or timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#include "camera.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#import <AVFoundation/AVCaptureDevice.h>
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
|
||||
FF_SUPPRESS_IO(); // #822
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeExternalUnknown]
|
||||
mediaType:AVMediaTypeVideo
|
||||
position:AVCaptureDevicePositionUnspecified];
|
||||
if (!session)
|
||||
return "Failed to create AVCaptureDeviceDiscoverySession";
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
|
||||
|
||||
#else
|
||||
|
||||
inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
|
||||
inline static const char* detectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
return "Unsupported platform";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
#include "disk.h"
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks);
|
||||
bool ffDiskMatchMountpoint(FFDiskOptions* options, const char* mountpoint)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char separator = ';';
|
||||
#else
|
||||
const char separator = ':';
|
||||
#endif
|
||||
|
||||
uint32_t mountpointLength = (uint32_t) strlen(mountpoint);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < options->folders.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&options->folders, startIndex, separator);
|
||||
|
||||
uint32_t folderLength = colonIndex - startIndex;
|
||||
if (folderLength == mountpointLength && memcmp(options->folders.chars + startIndex, mountpoint, mountpointLength) == 0)
|
||||
return true;
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
{
|
||||
@@ -9,7 +32,7 @@ static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
const char* error = ffDetectDisksImpl(disks);
|
||||
const char* error = ffDetectDisksImpl(options, disks);
|
||||
|
||||
if (error) return error;
|
||||
if (disks->length == 0) return "No disks found";
|
||||
|
||||
@@ -26,3 +26,6 @@ typedef struct FFDisk
|
||||
* If error is not set, disks contains at least one disk.
|
||||
*/
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks /* list of FFDisk */);
|
||||
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks);
|
||||
bool ffDiskMatchMountpoint(FFDiskOptions* options, const char* mountpoint);
|
||||
|
||||
@@ -90,7 +90,7 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
int size = getfsstat(NULL, 0, MNT_WAIT);
|
||||
|
||||
@@ -103,7 +103,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
for(struct statfs* fs = buf; fs < buf + size; ++fs)
|
||||
{
|
||||
if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
|
||||
if(__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if(!ffDiskMatchMountpoint(options, fs->f_mntonname))
|
||||
continue;
|
||||
}
|
||||
else if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
|
||||
continue;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
@@ -250,7 +250,7 @@ static void detectStats(FFDisk* disk)
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
FILE* mountsFile = setmntent("/proc/mounts", "r");
|
||||
if(mountsFile == NULL)
|
||||
@@ -260,7 +260,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
while((device = getmntent(mountsFile)))
|
||||
{
|
||||
if(!isPhysicalDevice(device))
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(options, device->mnt_dir))
|
||||
continue;
|
||||
}
|
||||
else if(!isPhysicalDevice(device))
|
||||
continue;
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
|
||||
@@ -6,23 +6,31 @@
|
||||
#include <winioctl.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
wchar_t buf[MAX_PATH + 1];
|
||||
uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf);
|
||||
if (length == 0 || length >= sizeof(buf) / sizeof(*buf))
|
||||
return "GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf) failed";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
wchar_t* mountpoint = buf + i;
|
||||
|
||||
ffStrbufSetWS(&buffer, mountpoint);
|
||||
i += buffer.length;
|
||||
|
||||
UINT driveType = GetDriveTypeW(mountpoint);
|
||||
if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
|
||||
if (__builtin_expect((long) options->folders.length, 0))
|
||||
{
|
||||
i += (uint32_t)wcslen(mountpoint);
|
||||
continue;
|
||||
if (!ffDiskMatchMountpoint(options, buffer.chars))
|
||||
continue;
|
||||
}
|
||||
else if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
continue;
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
|
||||
@@ -77,7 +85,7 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
else
|
||||
disk->createTime = 0;
|
||||
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
ffStrbufInitMove(&disk->mountpoint, &buffer);
|
||||
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
|
||||
{
|
||||
wchar_t volumeName[MAX_PATH + 1];
|
||||
@@ -91,8 +99,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
//Unsupported
|
||||
disk->filesUsed = 0;
|
||||
disk->filesTotal = 0;
|
||||
|
||||
i += disk->mountpoint.length;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -84,7 +84,7 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vram_used");
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
||||
|
||||
+30
-30
@@ -321,21 +321,42 @@ static void parseOption(FFdata* data, const char* key, const char* value);
|
||||
|
||||
static bool parseJsoncFile(const char* path)
|
||||
{
|
||||
yyjson_read_err error;
|
||||
yyjson_doc* doc = yyjson_read_file(path, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, &error);
|
||||
if (!doc)
|
||||
assert(!instance.state.configDoc);
|
||||
|
||||
{
|
||||
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
|
||||
yyjson_read_err error;
|
||||
instance.state.configDoc = yyjson_read_file(path, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, &error);
|
||||
if (!instance.state.configDoc)
|
||||
{
|
||||
fprintf(stderr, "Error: failed to parse JSON config file `%s` at pos %zu: %s\n", path, error.pos, error.msg);
|
||||
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
|
||||
{
|
||||
fprintf(stderr, "Error: failed to parse JSON config file `%s` at pos %zu: %s\n", path, error.pos, error.msg);
|
||||
exit(477);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
if (!yyjson_is_obj(root))
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
if (
|
||||
error ||
|
||||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
|
||||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
|
||||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
|
||||
(error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) ||
|
||||
false
|
||||
) {
|
||||
fprintf(stderr, "JsonConfig Error: %s\n", error);
|
||||
exit(477);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (instance.state.configDoc)
|
||||
yyjson_doc_free(instance.state.configDoc); // for `--load-config`
|
||||
|
||||
instance.state.configDoc = doc;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -779,27 +800,6 @@ static void parseArguments(FFdata* data, int argc, char** argv, void (*parser)(F
|
||||
|
||||
static void run(FFdata* data)
|
||||
{
|
||||
if (instance.state.configDoc)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
if (!yyjson_is_obj(root))
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
if (
|
||||
error ||
|
||||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
|
||||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
|
||||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
|
||||
(error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) ||
|
||||
false
|
||||
) {
|
||||
fprintf(stderr, "JsonConfig Error: %s\n", error);
|
||||
exit(477);
|
||||
}
|
||||
}
|
||||
|
||||
const bool useJsonConfig = data->structure.length == 0 && instance.state.configDoc;
|
||||
|
||||
if (useJsonConfig)
|
||||
|
||||
+7
-52
@@ -131,54 +131,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
|
||||
}
|
||||
}
|
||||
|
||||
static void printMountpoint(FFDiskOptions* options, const FFlist* disks, const char* mountpoint)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
|
||||
{
|
||||
if(ffStrbufEqualS(&disk->mountpoint, mountpoint))
|
||||
{
|
||||
printDisk(options, disk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disk found for mountpoint: %s", mountpoint);
|
||||
}
|
||||
|
||||
static void printMountpoints(FFDiskOptions* options, const FFlist* disks)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char separator = ';';
|
||||
#else
|
||||
const char separator = ':';
|
||||
#endif
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY mountpoints = ffStrbufCreateCopy(&options->folders);
|
||||
ffStrbufTrim(&mountpoints, separator);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < mountpoints.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&mountpoints, startIndex, separator);
|
||||
mountpoints.chars[colonIndex] = '\0';
|
||||
|
||||
printMountpoint(options, disks, mountpoints.chars + startIndex);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void printAutodetected(FFDiskOptions* options, const FFlist* disks)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
|
||||
{
|
||||
if(disk->type & ~options->showTypes)
|
||||
continue;
|
||||
|
||||
printDisk(options, disk);
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintDisk(FFDiskOptions* options)
|
||||
{
|
||||
FF_LIST_AUTO_DESTROY disks = ffListCreate(sizeof (FFDisk));
|
||||
@@ -190,10 +142,13 @@ void ffPrintDisk(FFDiskOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(options->folders.length == 0)
|
||||
printAutodetected(options, &disks);
|
||||
else
|
||||
printMountpoints(options, &disks);
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, disks)
|
||||
{
|
||||
if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes))
|
||||
continue;
|
||||
|
||||
printDisk(options, disk);
|
||||
}
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, disks)
|
||||
|
||||
Reference in New Issue
Block a user