Merge pull request #1492 from fastfetch-cli/dev

Release: v2.34.0
This commit is contained in:
Carter Li
2025-01-09 09:02:12 +08:00
committed by GitHub
72 changed files with 982 additions and 244 deletions
+38 -2
View File
@@ -232,6 +232,41 @@ jobs:
name: fastfetch-linux-riscv64
path: ./fastfetch-*.*
linux-ppc64le:
name: Linux-ppc64le
runs-on: ubuntu-22.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: run VM
uses: uraimo/run-on-arch-action@v2
id: runcmd
with:
arch: ppc64le
distro: ubuntu20.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-ppc64le
path: ./fastfetch-*.*
musl-amd64:
name: Musl-amd64
runs-on: ubuntu-latest
@@ -377,7 +412,7 @@ jobs:
architecture: x86-64
cpu_count: 4
shell: bash
version: '14.1'
version: '14.2'
run: |
uname -a
sudo pkg update
@@ -449,7 +484,7 @@ jobs:
architecture: x86-64
cpu_count: 4
shell: bash
version: '7.5'
version: '7.6'
run: |
uname -a
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio hwdata py3-requests
@@ -578,6 +613,7 @@ jobs:
- linux-aarch64
- linux-armv7
- linux-riscv64
- linux-ppc64le
- musl-amd64
- macos-universal
- freebsd-amd64
+36
View File
@@ -1,3 +1,39 @@
# 2.34.0
Changes:
* We now print distro pretty name if available (OS)
* This is a long requested feature. However, it may break some distros. File a bug with the content of `/etc/os-release` if it breaks your distro.
Bugfixes:
* Fix thunderbolt version of new MBPs (#1465, Host, macOS)
* Fix backlight name detection on FreeBSD (Brightness, FreeBSD)
* Fix Terminal detection when running fastfetch in `pk-command-not-found` (#1467, Terminal, Linux)
* Relax detection of terminals in NixOS (#1479, Terminal, Linux)
* Should fix konsole, ghostty and maybe others
* Fix core count output in multi-package platforms (CPU)
* Don't suppress the output of `preRun` (#1489)
* Fix battery percentage detection (Battery, NetBSD)
Features:
* Support ghostty terminal font detection (TerminalFont, Linux / macOS)
* Support `kitty-icat` image protocol, which uses `kitten icat` to generate image data
* Pros: support tmux; support gif animations; good performance
* Cons: due to the limitation of `kitten icat`, we need to clear the screen before displaying the image logo
* Support WM version detection (WM)
* In Linux, Hyprland & sway are supported currently
* Improve performance when stdout is redirected (TerminalSize)
* Report thermal zone temp if CPU temp is not available (CPU, Linux)
* Report sound server (Pipewire or PulseAudio) if available (#1454, Sound, Linux)
* Enable OpenGL & OpenCL detection on Android (OpenGL / OpenCL, Android)
* Detect & report MediaTek Dimensity 9000+ SOC name (CPU, Android)
* Support appman (am-user) package manager detection (Packages, Linux)
Logo:
* Add Lubuntu
* Update Xray_os
* Add SnigdhaOS
* Add Rhino Linux
# 2.33.0
Changes:
+24 -6
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.33.0
VERSION 2.34.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -70,8 +70,8 @@ cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR F
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS" OFF)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
@@ -534,7 +534,7 @@ if(LINUX)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_linux.c
src/detection/wm/wm_nosupport.c
src/detection/wm/wm_linux.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
@@ -617,7 +617,6 @@ elseif(FreeBSD)
src/common/sysctl.c
src/detection/battery/battery_bsd.c
src/detection/bios/bios_bsd.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_bsd.c
src/detection/bootmgr/bootmgr_bsd.c
@@ -690,6 +689,15 @@ elseif(FreeBSD)
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
if(DragonFly)
list(APPEND LIBFASTFETCH_SRC
src/detection/bluetooth/bluetooth_nosupport.c
)
else()
list(APPEND LIBFASTFETCH_SRC
src/detection/bluetooth/bluetooth_bsd.c
)
endif()
elseif(NetBSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
@@ -914,7 +922,7 @@ elseif(APPLE)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.m
src/detection/wifi/wifi_apple.m
src/detection/wm/wm_apple.c
src/detection/wm/wm_apple.m
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_apple.m
src/detection/camera/camera_apple.m
@@ -995,6 +1003,7 @@ elseif(WIN32)
src/util/windows/registry.c
src/util/windows/unicode.c
src/util/windows/wmi.cpp
src/util/windows/version.c
src/util/platform/FFPlatform_windows.c
src/util/binary_windows.c
)
@@ -1133,6 +1142,14 @@ else()
endif()
endif()
if(ANDROID)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib64 -Wl,-rpath,/system/lib64")
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib -Wl,-rpath,/system/lib")
endif()
endif()
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
ERROR_VARIABLE LD_MUSL_RESULT)
@@ -1468,6 +1485,7 @@ elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "usbhid"
PRIVATE "bluetooth"
)
if(NOT DragonFly)
target_link_libraries(libfastfetch
+29
View File
@@ -207,6 +207,35 @@ Try `export XAUTHORITY=$HOME/.Xauthority`
Try `fastfetch --wm-detect-plugin`. See also [#984](https://github.com/fastfetch-cli/fastfetch/issues/984)
### Q: How can I change the colors of my ASCII logo?
Try `fastfetch --logo-color-[1-9] <color>`. `[1-9]` is the index of color placeholders.
For example: `fastfetch --logo-color-1 red --logo-color-2 green`.
In JSONC, you can use:
```jsonc
{
"logo": {
"color": {
"1": "red",
"2": "green"
}
}
}
```
### Q: How to hide a key?
Set the key to a white space.
```jsonc
{
"key": " "
}
```
### Q: I want feature A / B / C. Will fastfetch support it?
Fastfetch is a system information tool. We only accept hardware or system level software feature requests. For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script:
+6
View File
@@ -1,3 +1,9 @@
fastfetch (2.33.0) jammy; urgency=medium
* Update to 2.33.0
-- Carter Li <zhangsongcui@live.cn> Thu, 26 Dec 2024 09:42:27 +0800
fastfetch (2.32.0) jammy; urgency=medium
* Update to 2.32.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.32.0_source.buildinfo universe/utils optional
fastfetch_2.33.0_source.buildinfo universe/utils optional
+5 -4
View File
@@ -275,11 +275,11 @@
"type": "string"
},
"osFormat": {
"description": "Output format of the module `OS`. See `-h format` for formatting syntax\n 1. {sysname}: Name of the kernel\n 2. {name}: Name of the OS\n 3. {pretty-name}: Pretty name of the OS\n 4. {id}: ID of the OS\n 5. {id-like}: ID like of the OS\n 6. {variant}: Variant of the OS\n 7. {variant-id}: Variant ID of the OS\n 8. {version}: Version of the OS\n 9. {version-id}: Version ID of the OS\n 10. {codename}: Version codename of the OS\n 11. {build-id}: Build ID of the OS\n 12. {arch}: Architecture of the OS",
"description": "Output format of the module `OS`. See `-h format` for formatting syntax\n 1. {sysname}: Name of the kernel\n 2. {name}: Name of the OS\n 3. {pretty-name}: Pretty name of the OS, if available\n 4. {id}: ID of the OS\n 5. {id-like}: ID like of the OS\n 6. {variant}: Variant of the OS\n 7. {variant-id}: Variant ID of the OS\n 8. {version}: Version of the OS\n 9. {version-id}: Version ID of the OS\n 10. {codename}: Version codename of the OS\n 11. {build-id}: Build ID of the OS\n 12. {arch}: Architecture of the OS",
"type": "string"
},
"packagesFormat": {
"description": "Output format of the module `Packages`. See `-h format` for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am}: Number of am packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {nix-all}: Total number of all nix packages\n 38. {flatpak-all}: Total number of all flatpak app packages\n 39. {brew-all}: Total number of all brew packages\n 40. {guix-all}: Total number of all guix packages",
"description": "Output format of the module `Packages`. See `-h format` for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {nix-all}: Total number of all nix packages\n 39. {flatpak-all}: Total number of all flatpak app packages\n 40. {brew-all}: Total number of all brew packages\n 41. {guix-all}: Total number of all guix packages",
"type": "string"
},
"physicaldiskFormat": {
@@ -315,7 +315,7 @@
"type": "string"
},
"soundFormat": {
"description": "Output format of the module `Sound`. See `-h format` for formatting syntax\n 1. {is-main}: Is main sound device\n 2. {name}: Device name\n 3. {volume-percentage}: Volume (in percentage num)\n 4. {identifier}: Identifier\n 5. {volume-percentage-bar}: Volume (in percentage bar)",
"description": "Output format of the module `Sound`. See `-h format` for formatting syntax\n 1. {is-main}: Is main sound device\n 2. {name}: Device name\n 3. {volume-percentage}: Volume (in percentage num)\n 4. {identifier}: Identifier\n 5. {volume-percentage-bar}: Volume (in percentage bar)\n 6. {platform-api}: Platform API used",
"type": "string"
},
"swapFormat": {
@@ -375,7 +375,7 @@
"type": "string"
},
"wmFormat": {
"description": "Output format of the module `WM`. See `-h format` for formatting syntax\n 1. {process-name}: WM process name\n 2. {pretty-name}: WM pretty name\n 3. {protocol-name}: WM protocol name\n 4. {plugin-name}: WM plugin name",
"description": "Output format of the module `WM`. See `-h format` for formatting syntax\n 1. {process-name}: WM process name\n 2. {pretty-name}: WM pretty name\n 3. {protocol-name}: WM protocol name\n 4. {plugin-name}: WM plugin name\n 5. {version}: WM version",
"type": "string"
},
"wifiFormat": {
@@ -432,6 +432,7 @@
"sixel",
"kitty",
"kitty-direct",
"kitty-icat",
"iterm",
"chafa",
"raw",
+3
View File
@@ -169,6 +169,9 @@ bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFst
? GetCurrentProcess()
: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (hProcess == NULL)
return false;
if (gui)
*gui = GetGuiResources(hProcess, GR_GDIOBJECTS) > 0;
+10 -1
View File
@@ -186,7 +186,8 @@
"data-raw": "Text data, printed as is",
"sixel": "Image file, printed as sixel codes",
"kitty": "Image file, printed as kitty graphics protocol",
"kitty_direct": "Image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)",
"kitty-direct": "Image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)",
"kitty-icat": "Image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed",
"iterm": "Image file, printed as iterm graphics protocol",
"chafa": "Image file, printed as ascii art using libchafa",
"raw": "Image file, printed as raw binary string",
@@ -351,6 +352,14 @@
"type": "path"
}
},
{
"long": "kitty-icat",
"desc": "Short for --logo-type kitty-icat --logo <path>",
"remark": "See \"--help logo-type\" for more info",
"arg": {
"type": "path"
}
},
{
"long": "iterm",
"desc": "Short for --logo-type iterm --logo <path>",
+3 -3
View File
@@ -46,7 +46,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
{
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
continue;
const char* desc = NULL;
if (!prop_dictionary_get_string(dict, "description", &desc))
continue;
@@ -88,7 +88,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
ffStrbufInit(&battery->manufactureDate);
battery->timeRemaining = -1;
battery->capacity = (double) curr / max;
battery->capacity = (double) curr / (double) max * 100.;
if (charging)
ffStrbufAppendS(&battery->status, "Charging, ");
else if (dischargeRate)
@@ -102,6 +102,6 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
}
}
prop_object_iterator_release(itKey);
return NULL;
}
+25
View File
@@ -0,0 +1,25 @@
#include "bluetooth.h"
#define L2CAP_SOCKET_CHECKED
#include <bluetooth.h>
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices)
{
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, bt_devremote_name_gen(dev->devname, &dev->bdaddr));
ffStrbufInitS(&device->address, bt_ntoa(&dev->bdaddr, NULL));
ffStrbufUpperCase(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = true;
return 0;
}
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
// struct hostent* ent = bt_gethostent();
if (bt_devenum((void*) enumDev, devices) < 0)
return "bt_devenum() failed";
return 0;
}
+1 -1
View File
@@ -34,7 +34,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
brightness->current = status.brightness;
struct backlight_info info;
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
if(ioctl(blfd, BACKLIGHTGETINFO, &info) == 0)
ffStrbufAppendS(&brightness->name, info.name);
else
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
+47 -1
View File
@@ -44,12 +44,20 @@ static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer)
if(
ffStrbufContainS(buffer, "cpu") ||
ffStrbufEqualS(buffer, "k10temp") || // AMD
ffStrbufEqualS(buffer, "fam15h_power") || // AMD
ffStrbufEqualS(buffer, "coretemp") // Intel
) return value / 1000.;
return 0.0/0.0;
}
static double detectTZTemp(FFstrbuf* buffer)
{
if (ffReadFileBuffer("/sys/class/thermal/thermal_zone0/temp", buffer))
return ffStrbufToDouble(buffer) / 1000.;
return 0.0/0.0;
}
static double detectCPUTemp(void)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
@@ -79,7 +87,7 @@ static double detectCPUTemp(void)
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
return 0.0/0.0;
return detectTZTemp(&buffer);
}
#ifdef __ANDROID__
@@ -136,6 +144,36 @@ static void detectQualcomm(FFCPUResult* cpu)
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 1 [SM4375]");
}
static void detectMediaTek(FFCPUResult* cpu)
{
// https://en.wikipedia.org/wiki/List_of_MediaTek_systems_on_chips
if (ffStrbufEqualS(&cpu->name, "MT6991"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9400 [MT6991]");
else if (ffStrbufEqualS(&cpu->name, "MT6991Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9400 [MT6991Z]");
else if (ffStrbufEqualS(&cpu->name, "MT6989Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300+ [MT6989Z]");
else if (ffStrbufEqualS(&cpu->name, "MT8796Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300+ [MT8796Z]");
else if (ffStrbufEqualS(&cpu->name, "MT6989"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300 [MT6989]");
else if (ffStrbufEqualS(&cpu->name, "MT8796"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300 [MT8796]");
else if (ffStrbufEqualS(&cpu->name, "MT6985W"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9200+ [MT6985W]");
else if (ffStrbufEqualS(&cpu->name, "MT6985"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9200 [MT6985]");
else if (ffStrbufEqualS(&cpu->name, "MT6983W"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000+ [MT6983W]");
else if (ffStrbufEqualS(&cpu->name, "MT8798Z/T"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000+ [MT8798Z/T]");
else if (ffStrbufEqualS(&cpu->name, "MT6983Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000 [MT6983Z]");
else if (ffStrbufEqualS(&cpu->name, "MT8798Z/C"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000 [MT8798Z/C]");
}
static void detectAndroid(FFCPUResult* cpu)
{
if (cpu->name.length == 0)
@@ -153,6 +191,8 @@ static void detectAndroid(FFCPUResult* cpu)
if (ffStrbufEqualS(&cpu->vendor, "QTI") && ffStrbufStartsWithS(&cpu->name, "SM"))
detectQualcomm(cpu);
else if (ffStrbufEqualS(&cpu->vendor, "MTK") && ffStrbufStartsWithS(&cpu->name, "MT"))
detectMediaTek(cpu);
}
#endif
@@ -188,6 +228,7 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
{
// https://github.com/Dr-Noob/cpufetch/issues/213#issuecomment-1927782105
ffStrbufSetStatic(&cpu->name, "Virtualized Apple Silicon");
ffStrbufGetlineRestore(&line, &len, cpuinfo);
return;
}
name = applePartId2name(partId);
@@ -243,7 +284,10 @@ static const char* parseCpuInfo(
&& cpu->name.length > 0 // #1202 #1204
#endif
)
{
ffStrbufGetlineRestore(&line, &len, cpuinfo);
break;
}
(void)(
// arm64 doesn't have "model name"; arm32 does have "model name" but its value is not useful.
@@ -512,6 +556,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
#if __x86_64__ || __i386__
cpu->packages = getPackageCount(&cpuinfo);
if (cpu->packages > 1)
cpu->coresPhysical *= cpu->packages;
#endif
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
+3
View File
@@ -62,6 +62,9 @@ static const char* parseEnv(void)
if(getenv("HYPRLAND_CMD") != NULL)
return "Hyprland";
if(getenv("SWAYSOCK") != NULL)
return "Sway";
#ifdef __linux__
if(
getenv("WAYLAND_DISPLAY") != NULL &&
+1 -1
View File
@@ -16,7 +16,7 @@ const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
const char* FF_GPU_VENDOR_NAME_REDHAT = "RedHat";
const char* FF_GPU_VENDOR_NAME_ORACLE = "Oracle";
const char* ffGetGPUVendorString(unsigned vendorId)
const char* ffGPUGetVendorString(unsigned vendorId)
{
// https://devicehunt.com/all-pci-vendors
switch (vendorId)
+1 -1
View File
@@ -46,7 +46,7 @@ typedef struct FFGPUResult
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGetGPUVendorString(unsigned vendorId);
const char* ffGPUGetVendorString(unsigned vendorId);
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__)
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
+1 -1
View File
@@ -161,7 +161,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
int vendorId;
if(ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL)
{
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
const char* vendorStr = ffGPUGetVendorString((unsigned) vendorId);
ffStrbufAppendS(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL)
gpu->type = FF_GPU_TYPE_INTEGRATED;
+1 -1
View File
@@ -38,7 +38,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
struct pci_conf* pc = &confs[i];
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(pc->pc_vendor));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor));
ffStrbufInit(&gpu->name);
ffStrbufInitS(&gpu->driver, pc->pd_name);
ffStrbufInit(&gpu->platformApi);
+2 -2
View File
@@ -15,7 +15,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_slot_match_iterator_create)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_device_next)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_system_cleanup)
{
// Requires root access
// Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci`
@@ -31,7 +31,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(dev->vendor_id));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->vendor_id));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
+1 -1
View File
@@ -435,7 +435,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
return "Invalid PCI device path";
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
+1 -1
View File
@@ -51,7 +51,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
uint32_t revision = (uint32_t) strtoul(pclass, NULL, 16);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
+2 -2
View File
@@ -72,7 +72,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
{
uint32_t vendorId = 0;
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
@@ -147,7 +147,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
{
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
}
detectFn(
+1 -1
View File
@@ -104,7 +104,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
DXCoreHardwareID hardwareId;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId)))
{
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
const char* vendorStr = ffGPUGetVendorString((unsigned) hardwareId.vendorID);
ffStrbufSetStatic(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && (options->driverSpecific || options->temp))
+4 -4
View File
@@ -109,11 +109,11 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
const char* version = hwModel->chars + strlen("Mac");
if(ffStrEquals(version, "16,3")) return "iMac (24-inch, 2024, Four Thunderbolt / USB 4 ports)";
if(ffStrEquals(version, "16,2")) return "iMac (24-inch, 2024, Two Thunderbolt / USB 4 ports)";
if(ffStrEquals(version, "16,1") ||
ffStrEquals(version, "16,6") ||
ffStrEquals(version, "16,8")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)";
if(ffStrEquals(version, "16,1")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)";
if(ffStrEquals(version, "16,6") ||
ffStrEquals(version, "16,8")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 5 ports)";
if(ffStrEquals(version, "16,7") ||
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 4 ports)";
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 5 ports)";
if(ffStrEquals(version, "16,15") ||
ffStrEquals(version, "16,10")) return "Mac mini (2024)";
if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)";
-2
View File
@@ -93,8 +93,6 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
DBusMessageIter arrayIterator;
data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
FF_STRBUF_AUTO_DESTROY desktopIdentity = ffStrbufCreate();
while(true)
{
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
+1 -1
View File
@@ -112,7 +112,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
{
cl_uint vendorId;
if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(vendorId), &vendorId, NULL) == CL_SUCCESS)
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
if (gpu->vendor.length == 0 && data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS)
ffStrbufSetS(&gpu->vendor, buffer);
}
+7
View File
@@ -4,6 +4,13 @@
#include <string.h>
#if __ANDROID__ && !defined(FF_HAVE_EGL)
// On Android, installing OpenGL headers is enough (mesa-dev)
#if __has_include(<EGL/egl.h>)
#define FF_HAVE_EGL 1
#endif
#endif
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
#define FF_HAVE_GL 1
+12 -6
View File
@@ -3,7 +3,7 @@
#if __has_include(<GL/gl.h>)
#include <GL/gl.h>
#elif __has_include(<OpenGL/gl.h>)
#elif __APPLE__
#define GL_SILENCE_DEPRECATION 1
#include <OpenGL/gl.h>
#else
@@ -64,9 +64,14 @@ static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data)
return NULL;
}
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data, bool gles)
{
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){
EGL_CONTEXT_CLIENT_VERSION, gles ? 2 : 1, // Try GLES 2.0+ first
EGL_NONE
});
if(data->context == EGL_NO_CONTEXT && gles) // Some ANGLE builds support GLES 1.1 only
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
if(data->context == EGL_NO_CONTEXT)
return "eglCreateContext returned EGL_NO_CONTEXT";
@@ -78,10 +83,11 @@ static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
{
// try use OpenGL API. If failed, use the default API (usually OpenGL ES)
data->ffeglBindAPI(EGL_OPENGL_API);
bool gles = !data->ffeglBindAPI(EGL_OPENGL_API);
EGLint eglConfigCount;
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
if(eglConfigCount == 0)
return "eglGetConfigs returned 0 configs";
@@ -94,7 +100,7 @@ static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
if(data->surface == EGL_NO_SURFACE)
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
const char* error = eglHandleSurface(result, data);
const char* error = eglHandleSurface(result, data, gles);
data->ffeglDestroySurface(data->display, data->surface);
return error;
}
@@ -148,7 +154,7 @@ const char* ffOpenGLDetectByEGL(FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
FF_SUPPRESS_IO();
// FF_SUPPRESS_IO();
return eglHandleData(result, &eglData);
}
-2
View File
@@ -5,8 +5,6 @@ void ffDetectOSImpl(FFOSResult* os)
{
ffStrbufSetStatic(&os->name, "Android");
ffStrbufSetStatic(&os->prettyName, "Android");
ffStrbufSetStatic(&os->id, "android");
ffSettingsGetAndroidProperty("ro.build.version.release", &os->version);
+11 -13
View File
@@ -54,18 +54,18 @@ static bool detectOSCodeName(FFOSResult* os)
case 14: ffStrbufSetStatic(&os->codename, "Mojave"); return true;
case 13: ffStrbufSetStatic(&os->codename, "High Sierra"); return true;
case 12: ffStrbufSetStatic(&os->codename, "Sierra"); return true;
case 11: ffStrbufSetStatic(&os->codename, "El Capitan"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 7: ffStrbufSetStatic(&os->codename, "Lion"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 5: ffStrbufSetStatic(&os->codename, "Leopard"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 4: ffStrbufSetStatic(&os->codename, "Tiger"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 11: ffStrbufSetStatic(&os->codename, "El Capitan"); return true;
case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); return true;
case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); return true;
case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); return true;
case 7: ffStrbufSetStatic(&os->codename, "Lion"); return true;
case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); return true;
case 5: ffStrbufSetStatic(&os->codename, "Leopard"); return true;
case 4: ffStrbufSetStatic(&os->codename, "Tiger"); return true;
case 3: ffStrbufSetStatic(&os->codename, "Panther"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 1: ffStrbufSetStatic(&os->codename, "Puma"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); return true;
case 1: ffStrbufSetStatic(&os->codename, "Puma"); return true;
case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); return true;
}
}
}
@@ -106,8 +106,6 @@ void ffDetectOSImpl(FFOSResult* os)
if(os->buildID.length == 0)
ffSysctlGetString("kern.osversion", &os->buildID);
if(os->prettyName.length == 0)
ffStrbufSetStatic(&os->prettyName, "macOS");
ffStrbufAppend(&os->versionID, &os->version);
if(!detectOSCodeName(os))
+9 -1
View File
@@ -80,6 +80,14 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Linux Lite "));
return;
}
else if(ffStrbufStartsWithS(&result->prettyName, "Rhino Linux "))
{
ffStrbufSetS(&result->name, "Rhino Linux");
ffStrbufSetS(&result->id, "rhinolinux");
ffStrbufSetS(&result->idLike, "ubuntu");
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Rhino Linux "));
return;
}
if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu"))
{
@@ -99,7 +107,7 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
return;
}
if(ffStrContains(xdgConfigDirs, "lxde") || ffStrContains(xdgConfigDirs, "lubuntu"))
if(ffStrContains(xdgConfigDirs, "lxqt") || ffStrContains(xdgConfigDirs, "lubuntu"))
{
ffStrbufSetS(&result->name, "Lubuntu");
ffStrbufSetS(&result->prettyName, "Lubuntu");
+3 -4
View File
@@ -13,6 +13,7 @@ void ffDetectOSImpl(FFOSResult* os)
const wchar_t* rawName = BrandingFormatString(L"%WINDOWS_LONG%");
ffStrbufSetWS(&os->variant, rawName);
GlobalFree((HGLOBAL)rawName);
ffStrbufSet(&os->prettyName, &os->variant);
ffStrbufTrimRight(&os->variant, ' ');
//WMI returns the "Microsoft" prefix while BrandingFormatString doesn't. Make them consistent.
@@ -22,14 +23,12 @@ void ffDetectOSImpl(FFOSResult* os)
if(ffStrbufStartsWithS(&os->variant, "Windows "))
{
ffStrbufAppendS(&os->name, "Windows");
ffStrbufAppendS(&os->prettyName, "Windows");
ffStrbufSubstrAfter(&os->variant, strlen("Windows ") - 1);
if(ffStrbufStartsWithS(&os->variant, "Server "))
{
ffStrbufAppendS(&os->name, " Server");
ffStrbufAppendS(&os->prettyName, " Server");
ffStrbufSubstrAfter(&os->variant, strlen(" Server") - 1);
}
@@ -38,7 +37,7 @@ void ffDetectOSImpl(FFOSResult* os)
ffStrbufSubstrAfter(&os->variant, index);
// Windows Server 20xx Rx
if(ffStrbufEndsWithC(&os->prettyName, 'r'))
if(ffStrbufEndsWithC(&os->name, 'r'))
{
if(os->variant.chars[0] == 'R' &&
ffCharIsDigit(os->variant.chars[1]) &&
@@ -56,6 +55,6 @@ void ffDetectOSImpl(FFOSResult* os)
ffStrbufClear(&os->variant);
}
ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars);
ffStrbufAppendF(&os->id, "%s %s", os->name.chars, os->version.chars);
ffStrbufSetStatic(&os->idLike, "Windows");
}
+2 -1
View File
@@ -4,7 +4,8 @@
typedef struct FFPackagesResult
{
uint32_t am;
uint32_t amSystem;
uint32_t amUser;
uint32_t apk;
uint32_t brew;
uint32_t brewCask;
+1 -1
View File
@@ -52,7 +52,7 @@ static void getBrewPackages(FFPackagesResult* result)
static uint32_t countMacPortsPackages(const char* dirname)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname);
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/var/macports/software");
ffStrbufAppendS(&baseDir, "/var/macports/software");
return getNumElements(baseDir.chars, DT_DIR);
}
+42 -18
View File
@@ -386,7 +386,29 @@ static uint32_t getRpmFromLibrpm(void)
#endif //FF_HAVE_RPM
static uint32_t getAM(FFstrbuf* baseDir)
static uint32_t getAMPackages(FFstrbuf* baseDir)
{
uint32_t baseLength = baseDir->length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
if (!dirp) return 0;
uint32_t result = 0;
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
if (entry->d_type == DT_DIR)
{
ffStrbufAppendF(baseDir, "/%s/remove", entry->d_name);
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
++result;
ffStrbufSubstrBefore(baseDir, baseLength);
}
}
return result;
}
static uint32_t getAMSystem(FFstrbuf* baseDir)
{
// #771
uint32_t baseDirLength = baseDir->length;
@@ -401,28 +423,27 @@ static uint32_t getAM(FFstrbuf* baseDir)
{
++result; // `am` itself is counted as a package too
ffStrbufSubstrBefore(baseDir, optDirLength);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
if(dirp)
{
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
if (entry->d_type == DT_DIR)
{
ffStrbufAppendF(baseDir, "/%s/AM-updater", entry->d_name);
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
++result;
ffStrbufSubstrBefore(baseDir, optDirLength);
}
}
}
result = getAMPackages(baseDir);
}
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
static uint32_t getAMUser(void)
{
// check if $XDG_CONFIG_HOME/appman/appman-config exists
FFstrbuf* baseDir = FF_LIST_GET(FFstrbuf, instance.state.platform.configDirs, 0);
uint32_t baseLen = baseDir->length;
ffStrbufAppendS(baseDir, "appman/appman-config");
FF_STRBUF_AUTO_DESTROY packagesPath = ffStrbufCreate();
if (ffReadFileBuffer(baseDir->chars, &packagesPath))
ffStrbufTrimRightSpace(&packagesPath);
ffStrbufSubstrBefore(baseDir, baseLen);
return packagesPath.length > 0 ? getAMPackages(&packagesPath) : 0;
}
static int compareHash(const void* a, const void* b)
{
return memcmp(a, b, 32);
@@ -565,7 +586,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
}
if (!(options->disabled & FF_PACKAGES_FLAG_PALUDIS_BIT)) packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
if (!(options->disabled & FF_PACKAGES_FLAG_OPKG_BIT)) packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:", "opkg"); // openwrt
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->am = getAM(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->amSystem = getAMSystem(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_SORCERY_BIT)) packageCounts->sorcery += getNumStrings(baseDir, "/var/state/sorcery/packages", ":installed:", "sorcery");
if (!(options->disabled & FF_PACKAGES_FLAG_GUIX_BIT))
{
@@ -678,4 +699,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
result->flatpakUser = getFlatpakPackages(&baseDir, "/.local/share");
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT))
result->amUser = getAMUser();
}
+1
View File
@@ -8,6 +8,7 @@ typedef struct FFSoundDevice
{
FFstrbuf identifier;
FFstrbuf name;
FFstrbuf platformApi;
uint8_t volume; // 0-100%
bool main;
bool active;
+1
View File
@@ -73,6 +73,7 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
device->volume = FF_SOUND_VOLUME_UNKNOWN;
ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId);
ffStrbufInit(&device->name);
ffStrbufInitStatic(&device->platformApi, "Core Audio");
ffCfStrGetString(name, &device->name);
uint32_t muted;
+2 -1
View File
@@ -39,7 +39,8 @@ const char* ffDetectSound(FFlist* devices)
FFSoundDevice* device = ffListAdd(devices);
ffStrbufInitS(&device->identifier, path);
ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info);
ffStrbufTrimRightSpace(&device->name);
ffStrbufTrimRightSpace(&device->name);
ffStrbufInitStatic(&device->platformApi, "OSS");
device->volume = mutemask & SOUND_MASK_VOLUME
? 0
: ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2;
+14 -9
View File
@@ -13,6 +13,7 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo
FFSoundDevice* device = ffListAdd(userdata);
ffStrbufInitS(&device->identifier, i->name);
ffStrbufInitS(&device->platformApi, "PulseAudio");
ffStrbufTrimRightSpace(&device->identifier);
ffStrbufInitS(&device->name, i->description);
ffStrbufTrimRightSpace(&device->name);
@@ -22,20 +23,24 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo
device->main = false;
}
static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *userdata)
static void paServerInfoCallback(FF_MAYBE_UNUSED pa_context *c, const pa_server_info *i, void *userdata)
{
FF_UNUSED(c);
if(!i) return;
if(!i)
return;
FF_STRBUF_AUTO_DESTROY api = ffStrbufCreate();
const char* realServer = strstr(i->server_name, "(on ");
if (realServer)
{
ffStrbufSetS(&api, realServer + strlen("(on "));
ffStrbufTrimRight(&api, ')');
}
else
ffStrbufSetF(&api, "%s %s", i->server_name, i->server_version);
FF_LIST_FOR_EACH(FFSoundDevice, device, *(FFlist*)userdata)
{
if(ffStrbufEqualS(&device->identifier, i->default_sink_name))
{
device->main = true;
break;
}
device->main = ffStrbufEqualS(&device->identifier, i->default_sink_name);
ffStrbufSet(&device->platformApi, &api);
}
}
+1
View File
@@ -65,6 +65,7 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
device->volume = FF_SOUND_VOLUME_UNKNOWN;
ffStrbufInitWS(&device->identifier, immDeviceId);
ffStrbufInit(&device->name);
ffStrbufInitStatic(&device->platformApi, "Core Audio APIs");
{
PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName;
+31
View File
@@ -48,6 +48,35 @@ static void detectAlacritty(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
static void detectGhostty(FFTerminalFontResult* terminalFont)
{
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
FFpropquery fontQueryToml[] = {
{"font-family =", &fontName},
{"font-size =", &fontSize},
};
if (
#if __APPLE__
!ffParsePropFileConfigValues("com.mitchellh.ghostty/config", 2, fontQueryToml) &&
#endif
!ffParsePropFileConfigValues("ghostty/config", 2, fontQueryToml)
) {
ffStrbufAppendS(&terminalFont->error, "Couldn't find file `ghostty/config`");
return;
}
if(fontName.length == 0)
ffStrbufAppendS(&fontName, "JetBrains Mono");
if(fontSize.length == 0)
ffStrbufAppendS(&fontSize, "13");
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont)
{
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
@@ -230,6 +259,8 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
detectTabby(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "contour"))
detectContour(&terminal->exe, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "ghostty"))
detectGhostty(terminalFont);
#ifndef _WIN32
else if(ffStrbufStartsWithIgnCaseS(&terminal->exe, "/dev/pts/"))
+45 -36
View File
@@ -15,41 +15,18 @@
#define _PATH_LOCALBASE "/usr/local"
#elif __NetBSD__
#define _PATH_LOCALBASE "/usr/pkg"
#endif
#elif _WIN32
#ifdef _WIN32
#include "util/windows/version.h"
#include <windows.h>
#include "util/mallocHelper.h"
#include <winver.h>
static bool getFileVersion(const char* exePath, FFstrbuf* version)
static bool getFileVersion(const FFstrbuf* exePath, FFstrbuf* version)
{
DWORD handle;
DWORD size = GetFileVersionInfoSizeA(exePath, &handle);
if(size > 0)
{
FF_AUTO_FREE void* versionData = malloc(size);
if(GetFileVersionInfoA(exePath, handle, size, versionData))
{
VS_FIXEDFILEINFO* verInfo;
UINT len;
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
{
ffStrbufAppendF(version, "%u.%u.%u.%u",
(unsigned)(( verInfo->dwFileVersionMS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwFileVersionMS >> 0 ) & 0xffff),
(unsigned)(( verInfo->dwFileVersionLS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwFileVersionLS >> 0 ) & 0xffff)
);
return true;
}
}
}
return false;
wchar_t exePathW[PATH_MAX];
int len = MultiByteToWideChar(CP_UTF8, 0, exePath->chars, (int)exePath->length, exePathW, ARRAY_SIZE(exePathW));
if (len <= 0) return false;
return ffGetFileVersion(exePathW, version);
}
#endif
static bool getExeVersionRaw(FFstrbuf* exe, FFstrbuf* version)
@@ -119,7 +96,7 @@ static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
}
#ifdef _WIN32
if(getFileVersion(exe->chars, version))
if(getFileVersion(exe, version))
{
ffStrbufSubstrBeforeLastC(version, '.');
return true;
@@ -312,7 +289,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath,
if(ffStrEqualsIgnCase(exeName, "powershell") || ffStrEqualsIgnCase(exeName, "powershell_ise"))
return getShellVersionWinPowerShell(exe, version);
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
#endif
return false;
@@ -621,6 +598,38 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
}
}
}
#elif __APPLE__
if (ffStrbufEndsWithS(exe, "/kitty.app/Contents/MacOS/kitty"))
{
ffStrbufSet(version, exe);
ffStrbufSubstrBeforeLastC(version, '/');
ffStrbufSubstrBeforeLastC(version, '/');
ffStrbufAppendS(version, "/Info.plist");
char buf[4096];
ssize_t size = ffReadFileData(version->chars, ARRAY_SIZE(buf) - 1, buf);
if (size > 0)
{
buf[size] = '\0';
const char* p = strstr(buf, "<key>CFBundleShortVersionString</key>");
if (p)
{
p += strlen("<key>CFBundleShortVersionString</key>");
p = strchr(p, '>');
if (p)
{
p++;
const char* end = strchr(p, '<');
if (end)
{
ffStrbufSetNS(version, (uint32_t) (end - p), p);
return true;
}
}
}
}
ffStrbufClear(version);
}
#endif
char versionHex[64];
@@ -706,7 +715,7 @@ static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
return true;
}
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
}
static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
@@ -716,7 +725,7 @@ static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
if(version->length)
return true;
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
}
#endif
@@ -875,7 +884,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
#ifdef _WIN32
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
#else
@@ -56,7 +56,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "fastfetch") || //994
ffStrbufEqualS(&result->processName, "flashfetch") ||
ffStrbufContainS(&result->processName, "debug") ||
ffStrbufContainS(&result->processName, "not-found") ||
ffStrbufContainS(&result->processName, "command-not-") ||
#ifdef __ANDROID__
ffStrbufEqualS(&result->processName, "proot") ||
#endif
@@ -313,11 +313,11 @@ static void setShellInfoDetails(FFShellResult* result)
static void setTerminalInfoDetails(FFTerminalResult* result)
{
if(ffStrbufStartsWithC(&result->processName, '.') && ffStrbufEndsWithS(&result->processName, "-wrapped"))
if(ffStrbufStartsWithC(&result->processName, '.') && ffStrbufContainS(&result->processName, "-wrap"))
{
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
// We use processName when detecting version and font, overriding it for simplification
ffStrbufSubstrBefore(&result->processName, result->processName.length - (uint32_t) strlen("-wrapped"));
ffStrbufSubstrBeforeLastC(&result->processName, '-');
ffStrbufSubstrAfter(&result->processName, 0);
}
@@ -5,39 +5,13 @@
#include "util/mallocHelper.h"
#include "util/windows/registry.h"
#include "util/windows/unicode.h"
#include "util/windows/version.h"
#include "util/stringUtils.h"
#include <windows.h>
#include <wchar.h>
#include <tlhelp32.h>
static bool getProductVersion(const wchar_t* filePath, FFstrbuf* version)
{
DWORD handle;
DWORD size = GetFileVersionInfoSizeW(filePath, &handle);
if(size > 0)
{
FF_AUTO_FREE void* versionData = malloc(size);
if(GetFileVersionInfoW(filePath, handle, size, versionData))
{
VS_FIXEDFILEINFO* verInfo;
UINT len;
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
{
ffStrbufAppendF(version, "%u.%u.%u.%u",
(unsigned)(( verInfo->dwProductVersionMS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionMS >> 0 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 0 ) & 0xffff)
);
return true;
}
}
}
return false;
}
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, const FFstrbuf* exePath, FFstrbuf* version);
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
@@ -113,7 +87,7 @@ static void setShellInfoDetails(FFShellResult* result)
if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0)
{
ffStrbufAppendS(&result->prettyName, " (with Clink ");
getProductVersion(module.szExePath, &result->prettyName);
ffGetFileVersion(module.szExePath, &result->prettyName);
ffStrbufAppendC(&result->prettyName, ')');
break;
}
@@ -2,6 +2,7 @@
#include "common/io/io.h"
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef __sun
@@ -11,7 +12,11 @@
bool ffDetectTerminalSize(FFTerminalSizeResult* result)
{
struct winsize winsize = {};
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
static int ttyfd = STDOUT_FILENO;
if (!isatty(ttyfd))
ttyfd = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
ioctl(ttyfd, TIOCGWINSZ, &winsize);
if (winsize.ws_row == 0 || winsize.ws_col == 0)
ffGetTerminalResponse("\e[18t", 2, "\e[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
+2 -9
View File
@@ -40,14 +40,7 @@ static void applyDriverName(VkPhysicalDeviceDriverPropertiesKHR* properties, FFs
static const char* detectVulkan(FFVulkanResult* result)
{
FF_LIBRARY_LOAD(vulkan, "dlopen libvulkan" FF_LIBRARY_EXTENSION " failed",
#if __ANDROID__
#if UINTPTR_MAX == UINT32_MAX
"/system/lib/"
#else
"/system/lib64/"
#endif
"libvulkan" FF_LIBRARY_EXTENSION, -1
#elif __APPLE__
#if __APPLE__
"libMoltenVK" FF_LIBRARY_EXTENSION, -1
#elif _WIN32
"vulkan-1" FF_LIBRARY_EXTENSION, -1
@@ -225,7 +218,7 @@ static const char* detectVulkan(FFVulkanResult* result)
ffStrbufInitS(&gpu->name, physicalDeviceProperties.properties.deviceName);
gpu->type = physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID));
ffStrbufInitS(&gpu->vendor, ffGPUGetVendorString(physicalDeviceProperties.properties.vendorID));
ffStrbufInitS(&gpu->driver, driverProperties.driverInfo);
VkPhysicalDeviceMemoryProperties memoryProperties = {};
+1
View File
@@ -3,3 +3,4 @@
#include "fastfetch.h"
const char* ffDetectWMPlugin(FFstrbuf* pluginName);
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FFWMOptions* options);
@@ -5,6 +5,7 @@
#include "util/stringUtils.h"
#include <ctype.h>
#import <Foundation/Foundation.h>
const char* ffDetectWMPlugin(FFstrbuf* pluginName)
{
@@ -38,3 +39,19 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName)
return NULL;
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "WindowServer"))
{
NSError* error;
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"file:///System/Library/CoreServices/WindowManager.app/Contents/version.plist"]
error:&error];
ffStrbufInitS(result, ((NSString*) dict[@"CFBundleVersion"]).UTF8String);
}
return NULL;
}
+113
View File
@@ -0,0 +1,113 @@
#include "wm.h"
#include "common/processing.h"
#include "common/io/io.h"
#include "detection/displayserver/displayserver.h"
#include "util/binary.h"
#include "util/path.h"
#include "util/stringUtils.h"
const char* ffDetectWMPlugin(FF_MAYBE_UNUSED FFstrbuf* pluginName)
{
return "Not supported on this platform";
}
static bool extractHyprlandVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (line[0] != 'v') return true;
int count = 0;
sscanf(line + 1, "%*d.%*d.%*d%n", &count);
if (count == 0) return true;
ffStrbufSetNS((FFstrbuf*) userdata, len - 1, line + 1);
return false;
}
static const char* getHyprland(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("Hyprland", &path);
if (error) return "Failed to find Hyprland executable path";
if (ffBinaryExtractStrings(path.chars, extractHyprlandVersion, result, (uint32_t) strlen("v0.0.0")) == NULL)
return NULL;
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // Hyprland 0.46.2 built from branch v0.46.2-b at... long and multi line
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufSubstrBeforeFirstC(result, ' ');
return NULL;
}
return "Failed to run command `Hyprland --version`";
}
static bool extractSwayVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (!ffStrStartsWith(line, "sway version ")) return true;
ffStrbufSetNS((FFstrbuf*) userdata, len - (uint32_t) strlen("sway version "), line + strlen("sway version "));
return false;
}
static const char* getSway(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("sway", &path);
if (error) return "Failed to find sway executable path";
if (ffBinaryExtractStrings(path.chars, extractSwayVersion, result, (uint32_t) strlen("v0.0.0")) == NULL)
{
ffStrbufTrimRightSpace(result);
return NULL;
}
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // sway version 1.10
ffStrbufSubstrAfterLastC(result, ' ');
ffStrbufTrimRightSpace(result);
return NULL;
}
return "Failed to run command `sway --version`";
}
static const char* getWslg(FFstrbuf* result)
{
if (!ffAppendFileBuffer("/mnt/wslg/versions.txt", result))
return "Failed to read /mnt/wslg/versions.txt";
if (!ffStrbufStartsWithS(result, "WSLg "))
return "Failed to find WSLg version";
ffStrbufSubstrBeforeFirstC(result, '\n');
ffStrbufSubstrBeforeFirstC(result, '+');
ffStrbufSubstrAfterFirstC(result, ':');
ffStrbufTrimLeft(result, ' ');
return NULL;
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "Hyprland"))
return getHyprland(result);
if (ffStrbufEqualS(wmName, "sway"))
return getSway(result);
if (ffStrbufEqualS(wmName, "WSLg"))
return getWslg(result);
return "Unsupported WM";
}
+5
View File
@@ -4,3 +4,8 @@ const char* ffDetectWMPlugin(FF_MAYBE_UNUSED FFstrbuf* pluginName)
{
return "Not supported on this platform";
}
const char* ffDetectWMVersion(FF_MAYBE_UNUSED const FFstrbuf* wmName, FF_MAYBE_UNUSED FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
return "Not supported on this platform";
}
+22
View File
@@ -3,6 +3,7 @@ extern "C"
#include "wm.h"
#include "common/io/io.h"
#include "detection/terminalshell/terminalshell.h"
#include "util/windows/version.h"
}
#include "util/windows/com.hpp"
@@ -64,3 +65,24 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName)
}
return NULL;
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "dwm.exe"))
{
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(FOLDERID_System, KF_FLAG_DEFAULT, NULL, &pPath)))
{
wchar_t fullPath[MAX_PATH];
wcscpy(fullPath, pPath);
wcscat(fullPath, L"\\dwm.exe");
ffGetFileVersion(fullPath, result);
}
CoTaskMemFree(pPath);
return NULL;
}
return "Not supported on this platform";
}
+20
View File
@@ -0,0 +1,20 @@
`.:/ossyyyysso/:.
`.:yyyyyyyyyyyyyyyyyy:.`
.:yyyyyyyyyyyyyyyyyyyyyyyy:.
.:yyyyyyyyyyyyyyyyyyyyyyyyyyyy:.
-yyyyyyyyyyyyyy${c2}+hNMMMNh+${c1}yyyyyyyyy-
:yy${c2}mNy+${c1}yyyyyyyy${c2}+Nmso++smMdhyysoo+${c1}yy:
-yy${c2}+MMMmmy${c1}yyyyyy${c2}hh${c1}yyyyyyyyyyyyyyyyyyy-
.yyyy${c2}NMN${c1}yy${c2}shhs${c1}yyy${c2}+o${c1}yyyyyyyyyyyyyyyyyyyy.
:yyyy${c2}oNM+${c1}yyyy${c2}+sso${c1}yyyyyyy${c2}ss${c1}yyyyyyyyyyyyy:
:yyyyy${c2}+dNs${c1}yyyyyyy${c2}++${c1}yyyyy${c2}oN+${c1}yyyyyyyyyyyy:
:yyyyy${c2}oMMmhysso${c1}yyyyyyyyyy${c2}mN+${c1}yyyyyyyyyyy:
:yyyyyy${c2}hMm${c1}yyyyy${c2}+++${c1}yyyyyyy${c2}+MN${c1}yyyyyyyyyyy:
.yyyyyyy${c2}ohmy+${c1}yyyyyyyyyyyyy${c2}NMh${c1}yyyyyyyyyy.
-yyyyyyyyyy${c2}++${c1}yyyyyyyyyyyy${c2}MMh${c1}yyyyyyyyy-
:yyyyyyyyyyyyyyyyyyyyy${c2}+mMN+${c1}yyyyyyyy:
-yyyyyyyyyyyyyyyyy${c2}+sdMMd+${c1}yyyyyyyy-
.:yyyyyyyyy${c2}hmdmmNMNdy+${c1}yyyyyyyy:.
.:yyyyyyy${c2}my${c1}yyyyyyyyyyyyyyy:.
`.:yyyy${c2}s${c1}yyyyyyyyyyyyy:.`
`.:/oosyyyysso/:.`
+12
View File
@@ -0,0 +1,12 @@
${c1} .;:;,. .:
${c1} 'coooooooo:oo.';.
${c1} ,oooooooooooooooo ;
${c1} clllcccllloooooooo;c:'o
${c1}.${c4};${c3}';:::::::::${c1}cclooooooo'
${c4}''',${c3}::::::::::::::${c1}ccclc.
${c4}.'''${c3};::::::::::${c2}l${c3}:::::::
${c4} ''''${c3},:::::::::${c2}kd${c3}.
${c4} .'''''${c3},;::${c2}ck:${c2}oW${c3};
${c4} ''''''''${c2}kXOM.
${c4} .,,:${c2}dXMK
${c4} ${c2}:k
+20
View File
@@ -0,0 +1,20 @@
WK0OO0X
WKOxk0XWNXkxN
WXOxk0N kk
WKkxOXW NxO
NX0ddk00OOOOkkkkkkkkk0
WKkxO0dOXXNNNNWWW WXKK
NxkN kxW XOxxdN
KoX WkxX WkxK Xd0
WxkW XkkX kkW NkxX
W0dK XxOWkkW XxkN
NkxX XoKWkxK Kd0
XkkN WOdN NkxX NxO
OxNKxOW XdO kk
kdk0W XoK WXkxN
WNNXKXXXXKKKK000OOdxkk0X
KdOO000KKKKXXXXX0xx0W
XoK N0kx0N
Nd0 NKOxOKW
Nkk0K0kxOKN
WXXXN
+33 -1
View File
@@ -2582,6 +2582,15 @@ static const FFlogo L[] = {
.colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_RED,
},
// Lubuntu
{
.names = {"lubuntu"},
.lines = FASTFETCH_DATATEXT_LOGO_LUBUNTU,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
},
// Lunar
{
.names = {"Lunar"},
@@ -3980,6 +3989,19 @@ static const FFlogo R[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// RhinoLinux
{
.names = {"Rhino Linux"},
.lines = FASTFETCH_DATATEXT_LOGO_RHINO,
.colors = {
FF_COLOR_FG_MAGENTA,
FF_COLOR_FG_LIGHT_BLUE,
FF_COLOR_FG_LIGHT_MAGENTA,
FF_COLOR_FG_MAGENTA,
},
.colorKeys = FF_COLOR_FG_MAGENTA,
.colorTitle = FF_COLOR_FG_MAGENTA,
},
// LAST
{},
};
@@ -4220,6 +4242,15 @@ static const FFlogo S[] = {
FF_COLOR_FG_WHITE,
},
},
// SnigdhaOS
{
.names = {"SnigdhaOS", "Snigdha"},
.lines = FASTFETCH_DATATEXT_LOGO_SMARTOS,
.colors = {
FF_COLOR_FG_CYAN,
FF_COLOR_FG_WHITE,
},
},
// Soda
{
.names = {"Soda"},
@@ -4991,9 +5022,10 @@ static const FFlogo X[] = {
.names = {"Xray_OS"},
.lines = FASTFETCH_DATATEXT_LOGO_XRAY_OS,
.colors = {
FF_COLOR_FG_256 "16",
FF_COLOR_FG_256 "15",
FF_COLOR_FG_256 "14",
FF_COLOR_FG_256 "16",
FF_COLOR_FG_256 "24",
}
},
// LAST
+125
View File
@@ -1,6 +1,7 @@
#include "image.h"
#include "common/io/io.h"
#include "common/printing.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include "util/base64.h"
#include "detection/terminalsize/terminalsize.h"
@@ -138,6 +139,127 @@ static bool printImageIterm(bool printError)
return true;
}
static bool printImageKittyIcat(bool printError)
{
const FFOptionsLogo* options = &instance.config.logo;
if (!ffPathExists(options->source.chars, FF_PATHTYPE_FILE))
{
if (printError)
fputs("Logo (kitty-icat): Failed to load image file\n", stderr);
return false;
}
fflush(stdout);
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if (options->position == FF_LOGO_POSITION_LEFT)
{
ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH",
(unsigned) options->paddingTop + 1,
(unsigned) options->paddingLeft + 1
);
}
else if (options->position == FF_LOGO_POSITION_TOP)
{
if (!options->width)
{
ffStrbufAppendNC(&buf, options->paddingTop, '\n');
ffStrbufAppendNC(&buf, options->paddingLeft, ' ');
}
else
{
if (printError)
fputs("Logo (kitty-icat): position top is not supported when logo width is set\n", stderr);
return false;
}
}
else if (options->position == FF_LOGO_POSITION_RIGHT)
{
if (printError)
fputs("Logo (kitty-icat): position right is not supported\n", stderr);
return false;
}
uint32_t prevLength = buf.length;
const char* error = NULL;
if (options->width)
{
char place[64];
snprintf(place,
ARRAY_SIZE(place),
"--place=%ux%u@%ux%u",
options->width,
options->height == 0 ? 9999 : options->height,
options->paddingLeft + 1,
options->paddingTop + 1);
error = ffProcessAppendStdOut(&buf, (char* []) {
"kitten",
"icat",
"-n",
"--align=center",
place,
"--scale-up",
options->source.chars,
NULL,
});
}
else
{
error = ffProcessAppendStdOut(&buf, (char* []) {
"kitten",
"icat",
"-n",
"--align=left",
options->source.chars,
NULL,
});
}
if (error)
{
if (printError)
fprintf(stderr, "Logo (kitty-icat): running `kitten icat` failed %s\n", error);
return false;
}
if (buf.length == prevLength)
{
if (printError)
fputs("Logo (kitty-icat): `kitten icat` returned empty output\n", stderr);
return false;
}
ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf);
if (options->position == FF_LOGO_POSITION_LEFT || options->position == FF_LOGO_POSITION_RIGHT)
{
uint16_t X = 0, Y = 0;
const char* error = ffGetTerminalResponse("\e[6n", 2, "%*[^0-9]%hu;%huR", &Y, &X);
if (error)
{
fprintf(stderr, "\nLogo (kitty-icat): fail to query cursor position: %s\n", error);
return true; // We already printed image logo, don't print ascii logo then
}
if (X < options->paddingLeft + options->width)
X = (uint16_t) (options->paddingLeft + options->width);
if (options->position == FF_LOGO_POSITION_LEFT)
instance.state.logoWidth = X + options->paddingRight - 1;
instance.state.logoHeight = Y;
fputs("\e[H", stdout);
}
else if (options->position == FF_LOGO_POSITION_TOP)
{
instance.state.logoWidth = instance.state.logoHeight = 0;
ffPrintCharTimes('\n', options->paddingRight);
}
return true;
}
static bool printImageKittyDirect(bool printError)
{
const FFOptionsLogo* options = &instance.config.logo;
@@ -957,6 +1079,9 @@ bool ffLogoPrintImageIfExists(FFLogoType type, bool printError)
if(type == FF_LOGO_TYPE_IMAGE_KITTY_DIRECT)
return printImageKittyDirect(printError);
if(type == FF_LOGO_TYPE_IMAGE_KITTY_ICAT)
return printImageKittyIcat(printError);
#if !defined(FF_HAVE_CHAFA)
if(type == FF_LOGO_TYPE_IMAGE_CHAFA)
{
+2 -1
View File
@@ -605,7 +605,8 @@ void ffLogoPrint(void)
ffStrbufIgnCaseEqualS(&terminal->processName, "kitty") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "konsole") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "wezterm") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst");
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "ghostty");
//Try to load the logo as an image. If it succeeds, print it and return.
if(logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false))
+1 -6
View File
@@ -69,12 +69,7 @@ void ffPrintCPU(FFCPUOptions* options)
if(coreTypes.length > 0)
ffStrbufAppendF(&str, " (%s)", coreTypes.chars);
else if(cpu.coresOnline > 1)
{
if(cpu.packages > 1)
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline / 2);
else
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
}
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
uint32_t freq = cpu.frequencyMax;
if(freq == 0)
+10 -35
View File
@@ -51,38 +51,6 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
ffStrbufAppend(result, &os->variantID);
ffStrbufAppendC(result, ')');
}
//Append architecture if it is missing
if(!ffStrbufContainIgnCase(result, &instance.state.platform.sysinfo.architecture))
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &instance.state.platform.sysinfo.architecture);
}
}
static void buildOutputNixOS(const FFOSResult* os, FFstrbuf* result)
{
ffStrbufAppendS(result, "NixOS");
if(os->buildID.length > 0)
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &os->buildID);
}
if(os->codename.length > 0)
{
ffStrbufAppendS(result, " (");
ffStrbufAppendC(result, (char) toupper(os->codename.chars[0]));
ffStrbufAppendS(result, os->codename.chars + 1);
ffStrbufAppendC(result, ')');
}
if(instance.state.platform.sysinfo.architecture.length > 0)
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &instance.state.platform.sysinfo.architecture);
}
}
void ffPrintOS(FFOSOptions* options)
@@ -99,11 +67,18 @@ void ffPrintOS(FFOSOptions* options)
{
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
if(ffStrbufIgnCaseCompS(&os->id, "nixos") == 0)
buildOutputNixOS(os, &result);
if(os->prettyName.length > 0)
ffStrbufAppend(&result, &os->prettyName);
else
buildOutputDefault(os, &result);
//Append architecture if it is missing
if(!ffStrbufContainIgnCase(&result, &instance.state.platform.sysinfo.architecture))
{
ffStrbufAppendC(&result, ' ');
ffStrbufAppend(&result, &instance.state.platform.sysinfo.architecture);
}
ffPrintLogoAndKey(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufPutTo(&result, stdout);
}
@@ -195,7 +170,7 @@ static FFModuleBaseInfo ffModuleInfo = {
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
{"Name of the kernel", "sysname"},
{"Name of the OS", "name"},
{"Pretty name of the OS", "pretty-name"},
{"Pretty name of the OS, if available", "pretty-name"},
{"ID of the OS", "id"},
{"ID like of the OS", "id-like"},
{"Variant of the OS", "variant"},
+8 -4
View File
@@ -62,7 +62,8 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE(paludis)
FF_PRINT_PACKAGE(winget)
FF_PRINT_PACKAGE(opkg)
FF_PRINT_PACKAGE(am)
FF_PRINT_PACKAGE_NAME(amSystem, "am")
FF_PRINT_PACKAGE_NAME(amUser, "appman")
FF_PRINT_PACKAGE(sorcery)
FF_PRINT_PACKAGE(lpkg)
FF_PRINT_PACKAGE(lpkgbuild)
@@ -108,7 +109,7 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_FORMAT_ARG(counts.paludis, "paludis"),
FF_FORMAT_ARG(counts.winget, "winget"),
FF_FORMAT_ARG(counts.opkg, "opkg"),
FF_FORMAT_ARG(counts.am, "am"),
FF_FORMAT_ARG(counts.amSystem, "am-system"),
FF_FORMAT_ARG(counts.sorcery, "sorcery"),
FF_FORMAT_ARG(counts.lpkg, "lpkg"),
FF_FORMAT_ARG(counts.lpkgbuild, "lpkgbuild"),
@@ -119,6 +120,7 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_FORMAT_ARG(counts.pacstall, "pacstall"),
FF_FORMAT_ARG(counts.mport, "mport"),
FF_FORMAT_ARG(counts.qi, "qi"),
FF_FORMAT_ARG(counts.amUser, "am-user"),
FF_FORMAT_ARG(nixAll, "nix-all"),
FF_FORMAT_ARG(flatpakAll, "flatpak-all"),
FF_FORMAT_ARG(brewAll, "brew-all"),
@@ -400,7 +402,8 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
#define FF_APPEND_PACKAGE_COUNT(name) yyjson_mut_obj_add_uint(doc, obj, #name, counts.name);
FF_APPEND_PACKAGE_COUNT(all)
FF_APPEND_PACKAGE_COUNT(am)
FF_APPEND_PACKAGE_COUNT(amSystem)
FF_APPEND_PACKAGE_COUNT(amUser)
FF_APPEND_PACKAGE_COUNT(apk)
FF_APPEND_PACKAGE_COUNT(brew)
FF_APPEND_PACKAGE_COUNT(brewCask)
@@ -469,7 +472,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Number of paludis packages", "paludis"},
{"Number of winget packages", "winget"},
{"Number of opkg packages", "opkg"},
{"Number of am packages", "am"},
{"Number of am-system packages", "am-system"},
{"Number of sorcery packages", "sorcery"},
{"Number of lpkg packages", "lpkg"},
{"Number of lpkgbuild packages", "lpkgbuild"},
@@ -480,6 +483,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Number of pacstall packages", "pacstall"},
{"Number of mport packages", "mport"},
{"Number of qi packages", "qi"},
{"Number of am-user (aka appman) packages", "am-user"},
{"Total number of all nix packages", "nix-all"},
{"Total number of all flatpak app packages", "flatpak-all"},
{"Total number of all brew packages", "brew-all"},
+3
View File
@@ -58,6 +58,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui
FF_FORMAT_ARG(percentageNum, "volume-percentage"),
FF_FORMAT_ARG(device->identifier, "identifier"),
FF_FORMAT_ARG(percentageBar, "volume-percentage-bar"),
FF_FORMAT_ARG(device->platformApi, "platform-api"),
}));
}
}
@@ -218,6 +219,7 @@ void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_m
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier);
yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &item->platformApi);
}
FF_LIST_FOR_EACH(FFSoundDevice, device, result)
@@ -241,6 +243,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Volume (in percentage num)", "volume-percentage"},
{"Identifier", "identifier"},
{"Volume (in percentage bar)", "volume-percentage-bar"},
{"Platform API used", "platform-api"},
}))
};
+17
View File
@@ -19,12 +19,22 @@ void ffPrintWM(FFWMOptions* options)
if(options->detectPlugin)
ffDetectWMPlugin(&pluginName);
FF_STRBUF_AUTO_DESTROY version = ffStrbufCreate();
if (instance.config.general.detectVersion)
ffDetectWMVersion(&result->wmProcessName, &version, options);
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&result->wmPrettyName, stdout);
if(version.length > 0)
{
putchar(' ');
ffStrbufWriteTo(&version, stdout);
}
if(result->wmProtocolName.length > 0)
{
fputs(" (", stdout);
@@ -48,6 +58,7 @@ void ffPrintWM(FFWMOptions* options)
FF_FORMAT_ARG(result->wmPrettyName, "pretty-name"),
FF_FORMAT_ARG(result->wmProtocolName, "protocol-name"),
FF_FORMAT_ARG(pluginName, "plugin-name"),
FF_FORMAT_ARG(version, "version"),
}));
}
}
@@ -116,11 +127,16 @@ void ffGenerateWMJsonResult(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc
if(options->detectPlugin)
ffDetectWMPlugin(&pluginName);
FF_STRBUF_AUTO_DESTROY version = ffStrbufCreate();
if (instance.config.general.detectVersion)
ffDetectWMVersion(&result->wmProcessName, &version, options);
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->wmProcessName);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->wmPrettyName);
yyjson_mut_obj_add_strbuf(doc, obj, "protocolName", &result->wmProtocolName);
yyjson_mut_obj_add_strbuf(doc, obj, "pluginName", &pluginName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &version);
}
static FFModuleBaseInfo ffModuleInfo = {
@@ -136,6 +152,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"WM pretty name", "pretty-name"},
{"WM protocol name", "protocol-name"},
{"WM plugin name", "plugin-name"},
{"WM version", "version"},
}))
};
+1 -10
View File
@@ -24,16 +24,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
options->processingTimeout = (int32_t) yyjson_get_int(val);
else if (ffStrEqualsIgnCase(key, "preRun"))
{
FF_STRBUF_AUTO_DESTROY _ = ffStrbufCreate();
const char* error = ffProcessAppendStdOut(&_, (char* const[]) {
#ifdef _WIN32
"cmd.exe", "/C",
#else
"/bin/sh", "-c",
#endif
(char*) yyjson_get_str(val), NULL
});
if (error)
if (system(yyjson_get_str(val)) < 0)
return "Failed to execute preRun command";
}
else if (ffStrEqualsIgnCase(key, "detectVersion"))
+7
View File
@@ -63,6 +63,7 @@ logoType:
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
{ "kitty-icat", FF_LOGO_TYPE_IMAGE_KITTY_ICAT },
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
@@ -172,6 +173,11 @@ logoType:
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_KITTY_DIRECT;
}
else if(ffStrEqualsIgnCase(key, "--kitty-icat"))
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_KITTY_ICAT;
}
else if(ffStrEqualsIgnCase(key, "--iterm"))
{
ffOptionParseString(key, value, &options->source);
@@ -283,6 +289,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
{ "kitty-icat", FF_LOGO_TYPE_IMAGE_KITTY_ICAT },
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
+1
View File
@@ -17,6 +17,7 @@ typedef enum __attribute__((__packed__)) FFLogoType
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
+16 -6
View File
@@ -225,12 +225,6 @@ void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value)
ffStrbufAppendNS(strbuf, length, value);
}
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
{
ffStrbufClear(strbuf);
ffStrbufAppendNS(strbuf, value->length, value->chars);
}
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c)
{
if(strbuf->length == 0)
@@ -576,6 +570,22 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
return true;
}
/// @brief Restore the end of a line that was modified by ffStrbufGetline.
/// @warning This function should be called before breaking an ffStrbufGetline loop.
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
{
assert(buffer && lineptr && n);
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
assert(!*lineptr || (*lineptr >= buffer->chars && *lineptr <= buffer->chars + buffer->length));
if (!*lineptr)
return;
*lineptr += *n;
if (*lineptr < buffer->chars + buffer->length)
**lineptr = '\n';
}
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf)
{
if (strbuf->allocated == 0) return false; // Doesn't work with static strings
+19 -3
View File
@@ -49,7 +49,6 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c);
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c);
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
@@ -91,6 +90,7 @@ void ffStrbufUpperCase(FFstrbuf* strbuf);
void ffStrbufLowerCase(FFstrbuf* strbuf);
bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer);
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer);
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
@@ -102,8 +102,13 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
static inline void ffStrbufInitCopy(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict src)
{
ffStrbufInitA(strbuf, src->allocated);
ffStrbufAppend(strbuf, src);
if (src->allocated == 0) // static string
memcpy(strbuf, src, sizeof(FFstrbuf));
else
{
ffStrbufInitA(strbuf, src->allocated);
ffStrbufAppend(strbuf, src);
}
}
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateCopy(const FFstrbuf* src)
@@ -209,6 +214,17 @@ static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
}
static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
{
assert(value && value != strbuf);
if (strbuf->allocated == 0 && value->allocated == 0)
{
memcpy(strbuf, value, sizeof(FFstrbuf));
return;
}
ffStrbufSetNS(strbuf, value->length, value->chars);
}
static inline void ffStrbufInit(FFstrbuf* strbuf)
{
extern char* CHAR_NULL_PTR;
+5 -2
View File
@@ -21,7 +21,8 @@ static void getExePath(FFPlatform* platform)
char exePath[PATH_MAX + 1];
#ifdef __linux__
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
exePath[exePathLen] = '\0';
if (exePathLen >= 0)
exePath[exePathLen] = '\0';
#elif defined(__APPLE__)
int exePathLen = proc_pidpath((int) getpid(), exePath, sizeof(exePath));
#elif defined(__FreeBSD__) || defined(__NetBSD__)
@@ -44,7 +45,8 @@ static void getExePath(FFPlatform* platform)
size_t exePathLen = 0;
#elif defined(__sun)
ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1);
exePath[exePathLen] = '\0';
if (exePathLen >= 0)
exePath[exePathLen] = '\0';
#endif
if (exePathLen > 0)
{
@@ -107,6 +109,7 @@ static void getCacheDir(FFPlatform* platform)
static void getConfigDirs(FFPlatform* platform)
{
// Always make sure `${XDG_CONFIG_HOME:-$HOME/.config}` is the first entry
platformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME");
ffPlatformPathAddHome(&platform->configDirs, platform, ".config/");
+6 -6
View File
@@ -31,13 +31,12 @@ static void getExePath(FFPlatform* platform)
static void getHomeDir(FFPlatform* platform)
{
PWSTR pPath;
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath)))
{
ffStrbufSetWS(&platform->homeDir, pPath);
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
CoTaskMemFree(pPath);
}
else
{
@@ -45,28 +44,29 @@ static void getHomeDir(FFPlatform* platform)
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
CoTaskMemFree(pPath);
}
static void getCacheDir(FFPlatform* platform)
{
PWSTR pPath;
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath)))
{
ffStrbufSetWS(&platform->cacheDir, pPath);
ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
CoTaskMemFree(pPath);
}
else
{
ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
}
CoTaskMemFree(pPath);
}
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
{
PWSTR pPath;
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath)))
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateWS(pPath);
@@ -74,8 +74,8 @@ static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
ffStrbufEnsureEndsWithC(&buffer, '/');
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
CoTaskMemFree(pPath);
}
CoTaskMemFree(pPath);
}
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
+31
View File
@@ -0,0 +1,31 @@
#include "util/windows/version.h"
#include "util/mallocHelper.h"
#include <windows.h>
bool ffGetFileVersion(const wchar_t* filePath, FFstrbuf* version)
{
DWORD handle;
DWORD size = GetFileVersionInfoSizeW(filePath, &handle);
if(size > 0)
{
FF_AUTO_FREE void* versionData = malloc(size);
if(GetFileVersionInfoW(filePath, handle, size, versionData))
{
VS_FIXEDFILEINFO* verInfo;
UINT len;
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
{
ffStrbufAppendF(version, "%u.%u.%u.%u",
(unsigned)(( verInfo->dwProductVersionMS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionMS >> 0 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 0 ) & 0xffff)
);
return true;
}
}
}
return false;
}
+3
View File
@@ -0,0 +1,3 @@
#include "fastfetch.h"
bool ffGetFileVersion(const wchar_t* filePath, FFstrbuf* version);
+42
View File
@@ -593,6 +593,48 @@ int main(void)
VERIFY(ffStrbufRemoveDupWhitespaces(&strbuf) == false);
VERIFY(strcmp(strbuf.chars, " ") == 0);
{
ffStrbufSetStatic(&strbuf, "abcdef");
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateCopy(&strbuf);
VERIFY(newStr.allocated == 0);
VERIFY(newStr.chars == strbuf.chars);
}
{
ffStrbufSetStatic(&strbuf, "abcdef");
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateS("123456");
ffStrbufSet(&newStr, &strbuf);
VERIFY(newStr.allocated > 0);
VERIFY(newStr.chars != strbuf.chars);
VERIFY(ffStrbufEqualS(&newStr, "abcdef"));
}
{
ffStrbufSetStatic(&strbuf, "abcdefghijkl");
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateS("123456");
ffStrbufSet(&newStr, &strbuf);
VERIFY(newStr.allocated > 0);
VERIFY(newStr.chars != strbuf.chars);
VERIFY(ffStrbufEqualS(&newStr, "abcdefghijkl"));
}
{
ffStrbufClear(&strbuf);
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateCopy(&strbuf);
VERIFY(newStr.allocated == 0);
VERIFY(newStr.chars == strbuf.chars);
VERIFY(newStr.chars[0] == '\0');
}
{
ffStrbufClear(&strbuf);
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateS("123456");
ffStrbufSet(&newStr, &strbuf);
VERIFY(newStr.allocated > 0);
VERIFY(newStr.chars != strbuf.chars);
VERIFY(ffStrbufEqualS(&newStr, ""));
}
//Success
puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
}