Compare commits

..

42 Commits

Author SHA1 Message Date
Carter Li ba8a21142f Merge pull request #1873 from fastfetch-cli/dev
Release: v2.49.0
2025-07-31 13:54:49 +08:00
李通洲 eca3625165 Battery / Uptime: update document of custom format 2025-07-31 13:32:18 +08:00
李通洲 677e920dc8 Battery: address copilot feedback 2025-07-31 10:51:53 +08:00
李通洲 38c0b24daa WM (Linux): fix a copy-paste error. 2025-07-31 10:50:45 +08:00
李通洲 4e05502d7a Release: v2.49.0 2025-07-31 10:42:09 +08:00
李通洲 d0928a63bf Doc: update readme 2025-07-30 16:18:04 +08:00
李通洲 aa0bbd5aee Percent: add option --percent-width 2025-07-30 15:06:16 +08:00
李通洲 ce554dbdd0 Uptime / Battery: add formatted duration string in custom format 2025-07-30 15:03:23 +08:00
李通洲 a0174e8666 Global: add new unit related options
1. `--<module>-space-before-unit`
2. `--duration-abbreviation`
3. various code refactoring and cleanups
2025-07-30 15:03:23 +08:00
李通洲 8be419cfd6 DiskIO: fix wrong /s assignment in custom format
Fix #1871
2025-07-30 09:05:33 +08:00
李通洲 ca79bae36e Packages (Windows): find scoop installation path by parsing scoop config file 2025-07-29 19:29:40 +08:00
Carter Li b1f0248fb3 Font (Linux): parse unicode escaped string stored by qt5ct
Fix #1864
2025-07-29 18:25:34 +08:00
Carter Li 77dd18466b FFstrbuf: add function ffStrbufAppendUtf32CodePoint 2025-07-29 16:36:21 +08:00
李通洲 5bb6e22679 GPU (Intel): read render engine temperature only 2025-07-29 14:23:56 +08:00
Carter Li 9ea9291ab8 WM (Linux): add labwc version detection support 2025-07-29 10:20:05 +08:00
Carter Li 6ec73863ab CPU (Android): make SOC detection more loose
It's less accurate, but higher chance to match.
2025-07-29 09:28:41 +08:00
Carter Li 8c2f93151d CPU (Android): add more QSD SOCs 2025-07-29 09:28:36 +08:00
李通洲 71ddc4ffc6 Disk: update default value of hideFolders
Fix #1869
2025-07-28 23:49:27 +08:00
李通洲 4909d693e3 Packages (Windows): don't rely on the existance of $SCOOP when detecting scoop packages
Fix #1868
2025-07-28 23:41:48 +08:00
李通洲 fe76bbe68a Logo (Builtin): remove Evolinx 2025-07-28 23:06:15 +08:00
李通洲 d1f20822f1 GPU (macOS): silence compiler warnings 2025-07-28 15:39:35 +08:00
李通洲 1ed804db52 Wifi (macOS): use sudo wdutil info on Tahoe
sudo, you know it.
2025-07-28 15:35:02 +08:00
李通洲 0e8b9bec2d FFstrbuf: add function ffStrbufSubstr 2025-07-28 15:35:02 +08:00
李通洲 a3182c31cb Chore: add FF_C_NONNULL 2025-07-28 15:35:02 +08:00
Darloli d2f2c76dfc Version: correct the variable name 'name' to 'project-name' 2025-07-26 08:33:34 +08:00
Darloli 2d1ae1b4c5 Users: correct the variable name 'session' to 'session-name' 2025-07-26 08:33:34 +08:00
李通洲 316409ecc3 LocalIP: cleanup printing code 2025-07-24 20:12:48 +08:00
李通洲 f0fc38bcb5 LocalIP (Windows): fix link speed calcuation 2025-07-24 20:11:04 +08:00
李通洲 e7a6b84107 LocalIP (Windows): ignore stopped interfaces 2025-07-24 19:31:41 +08:00
李通洲 02c3254961 Netif (Windows): correct default route detection (v2) 2025-07-24 19:31:41 +08:00
李通洲 a90e1d7ccf JsonSchema: improve definitions of colors and conditions [ci skip]
Fix #1862
2025-07-23 09:31:25 +08:00
Carter Li 6cdd64ac55 CI (Haiku): remove work around 2025-07-22 22:10:00 +08:00
Carter Li aa1201ffb8 Editor: correct the variable name full-path to path
Fix #1861
2025-07-22 22:06:26 +08:00
Carter Li 9b491c2f49 Wifi (Linux): fix interface status when the interface is up but not connected 2025-07-22 22:03:53 +08:00
李通洲 be3e2ba521 Presets: improve 25.jsonc; add verbose comments [ci skip] 2025-07-22 15:46:36 +08:00
李通洲 ccbb9e90ea Netif (Windows): fix default route detection when the default adapter is disabled
This commit addresses an issue where the default route detection on Windows incorrectly identified a disabled adapter as the default route. Previously, when a user disabled the adapter configured as the default route, the system still reported it as active due to stale routing table entries.
2025-07-21 20:24:43 +08:00
李通洲 d07fe997a9 CI (NetBSD): remove opencl support to fix building 2025-07-21 14:41:02 +08:00
李通洲 b60996bcd1 Packages (Linux): remove qi support
Close #1858
2025-07-21 14:19:12 +08:00
李通洲 272c0aad9c Packages (Linux): improve accuracy of flatpak count detection
Fix #1856
2025-07-21 14:06:19 +08:00
Carter Li 7566f10bb6 Logo (Builtin): add Aeon
Fix  #1855
2025-07-20 16:47:35 +08:00
Carter Li 847b76b863 GPU (Linux): add GPU temp detection for nouveau driver 2025-07-19 18:17:28 +08:00
Carter Li 5c0ad030cc GPU (Linux): support advanced detection for nouveau driver 2025-07-19 16:47:42 +08:00
71 changed files with 1566 additions and 467 deletions
+1 -30
View File
@@ -628,7 +628,7 @@ jobs:
version: '10.1'
run: |
uname -a
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick opencl-headers ocl-icd
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -690,34 +690,6 @@ jobs:
- name: checkout repository
uses: actions/checkout@v4
- name: Fixup VM
uses: cross-platform-actions/action@master
with:
operating_system: haiku
version: 'r1beta5'
architecture: x86-64
cpu_count: 4
shell: bash
sync_files: false
shutdown_vm: false
run: |
mv '/home/runner/work' '/boot/home/work'
ln -sf '/boot/home/work' '/home/runner/work'
- name: Sync files to VM
uses: cross-platform-actions/action@master
with:
operating_system: haiku
version: 'r1beta5'
architecture: x86-64
cpu_count: 4
shell: bash
sync_files: runner-to-vm
shutdown_vm: false
run: |
chown -R $(id -u):$(id -g) $(pwd)
ls -l
- name: run VM
uses: cross-platform-actions/action@master
with:
@@ -726,7 +698,6 @@ jobs:
architecture: x86-64
cpu_count: 4
shell: bash
sync_files: vm-to-runner
run: |
uname -a
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
+48
View File
@@ -1,3 +1,51 @@
# 2.49.0
Deprecation Notice:
* In fastfetch v2, the JSONC configuration format has been introduced, while command line configuration flags are kept for compatibility. Although they have the same effects, they use two different code paths, and as the number of flags grows, the codebase is becoming increasingly difficult to maintain.
* Removal of module config flags is planned for **v2.50.0**, which will also fix a long-standing issue #1477.
* Removal of most other config flags is also planned for later versions.
* Keys of JSON configuration files will be all case-sensitive. Currently they are inconsistent. Planned for **v2.50.0**.
Changes:
* Due to more restrictive permissions in macOS Tahoe, SSID detection on macOS 26+ requires root privileges. `<redacted>` will be displayed otherwise.
Features:
* Improve `nouveau` driver support for `--gpu-driver-specific` (GPU, Linux)
* VRAM size detection
* GPU temperature detection
* Core count detection (when available)
* Improve Scoop package manager detection (Packages, Windows)
* Support [`scoop-global`](https://github.com/ScoopInstaller/Install?tab=readme-ov-file#advanced-installation)
* Read Scoop's config file to find the installation path of Scoop
* Improve ARM SoC detection (CPU, Android)
* Make SoC detection more lenient. Higher chance to match at the cost of accuracy.
* Add more Snapdragon SoC names
* Support labwc WM version detection, used for XFCE4 on Wayland (WM, Linux)
* Improve accuracy of GPU temperature detection for Intel dedicated GPUs on Windows (GPU, Windows)
* Parse unicode escaped strings generated by qt5ct (#1864, Font, Linux)
* Add `--{duration,percent,size,freq,temp}-space-before-unit [always|never]` options to add a space before the unit when printing duration, percent, size, frequency and temperature values
* Add `--duration-abbreviation` to abbreviate duration values in custom format
* For example: `1 day, 2 hours, 3 mins` will be displayed as `1d 2h 3m`
* Add `--percent-with` to pad the percent value with spaces to a fixed width
* For example: `--percent-with 3` will display ` 50%` instead of `50%`; useful for aligning percent values in custom format
Bugfixes:
* Improve accuracy of Flatpak count detection (#1856, Packages, Linux)
* Remove qi package manager support (#1858, Packages, Linux)
* Fix LocalIP module on Windows (LocalIP, Windows)
* Fix default route detection when multiple network interfaces are connected
* Fix link speed calculation
* Fix interface status when the interface is up but not connected (Wifi, Linux)
* Fix variable names in custom format (#1861)
* `full-path` to `path` (Editor)
* `session` to `session-name` (Users)
* `name` to `project-name` (Version)
* Fix wrong /s assignment in custom format (#1871, DiskIO)
Logos:
* Add `Aeon`
* Remove `Evolinx`
# 2.48.1
Features:
+5 -2
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.48.1
VERSION 2.49.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -351,10 +351,11 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
#######################
set(LIBFASTFETCH_SRC
src/common/percent.c
src/common/commandoption.c
src/common/duration.c
src/common/font.c
src/common/format.c
src/common/frequency.c
src/common/init.c
src/common/jsonconfig.c
src/common/library.c
@@ -363,9 +364,11 @@ set(LIBFASTFETCH_SRC
src/common/networking/networking_common.c
src/common/option.c
src/common/parsing.c
src/common/percent.c
src/common/printing.c
src/common/properties.c
src/common/settings.c
src/common/size.c
src/common/temps.c
src/detection/bluetoothradio/bluetoothradio.c
src/detection/bootmgr/bootmgr.c
+65 -12
View File
@@ -3,7 +3,8 @@
"$defs": {
"colors": {
"type": "string",
"enum": [
"description": "https://github.com/fastfetch-cli/fastfetch/wiki/Color-Format-Specification",
"examples": [
"reset_", "bright_", "dim_", "italic_", "underline_", "blink_", "inverse_", "hidden_", "strike_", "light_",
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "default"
]
@@ -52,6 +53,7 @@
"bar-monochrome"
]
},
"uniqueItems": true,
"default": [
"num",
"num-color"
@@ -150,13 +152,13 @@
"properties": {
"system": {
"description": "System name to match",
"type": "string",
"oneOf": [
{
"$ref": "#/$defs/systems"
},
{
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/$defs/systems"
},
@@ -170,13 +172,13 @@
},
"!system": {
"description": "System name to not match",
"type": "string",
"oneOf": [
{
"$ref": "#/$defs/systems"
},
{
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/$defs/systems"
},
@@ -190,13 +192,13 @@
},
"arch": {
"description": "Architecture to match",
"type": "string",
"oneOf": [
{
"$ref": "#/$defs/architectures"
},
{
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/$defs/architectures"
},
@@ -210,13 +212,13 @@
},
"!arch": {
"description": "Architecture to not match",
"type": "string",
"oneOf": [
{
"$ref": "#/$defs/architectures"
},
{
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/$defs/architectures"
},
@@ -230,10 +232,28 @@
}
}
},
"spaceBeforeUnit": {
"type": "string",
"description": "Whether to put a space before the unit",
"oneOf": [
{
"const": "default",
"description": "Use the default behavior of the module"
},
{
"const": "always",
"description": "Always add a space before the unit"
},
{
"const": "never",
"description": "Never add a space before the unit"
}
]
},
"batteryFormat": {
"description": "Output format of the module `Battery`. See Wiki for formatting syntax\n 1. {manufacturer}: Battery manufacturer\n 2. {model-name}: Battery model name\n 3. {technology}: Battery technology\n 4. {capacity}: Battery capacity (percentage num)\n 5. {status}: Battery status\n 6. {temperature}: Battery temperature (formatted)\n 7. {cycle-count}: Battery cycle count\n 8. {serial}: Battery serial number\n 9. {manufacture-date}: Battery manufactor date\n 10. {capacity-bar}: Battery capacity (percentage bar)\n 11. {time-days}: Battery time remaining days\n 12. {time-hours}: Battery time remaining hours\n 13. {time-minutes}: Battery time remaining minutes\n 14. {time-seconds}: Battery time remaining seconds",
"description": "Output format of the module `Battery`. See Wiki for formatting syntax\n 1. {manufacturer}: Battery manufacturer\n 2. {model-name}: Battery model name\n 3. {technology}: Battery technology\n 4. {capacity}: Battery capacity (percentage num)\n 5. {status}: Battery status\n 6. {temperature}: Battery temperature (formatted)\n 7. {cycle-count}: Battery cycle count\n 8. {serial}: Battery serial number\n 9. {manufacture-date}: Battery manufactor date\n 10. {capacity-bar}: Battery capacity (percentage bar)\n 11. {time-days}: Battery time remaining days\n 12. {time-hours}: Battery time remaining hours\n 13. {time-minutes}: Battery time remaining minutes\n 14. {time-seconds}: Battery time remaining seconds\n 15. {time-formatted}: Battery time remaining (formatted)",
"type": "string"
},
"biosFormat": {
@@ -317,7 +337,7 @@
"type": "string"
},
"editorFormat": {
"description": "Output format of the module `Editor`. See Wiki for formatting syntax\n 1. {type}: Type (Visual / Editor)\n 2. {name}: Name\n 3. {exe-name}: Exe name of real path\n 4. {full-path}: Full path of real path\n 5. {version}: Version",
"description": "Output format of the module `Editor`. See Wiki for formatting syntax\n 1. {type}: Type (Visual / Editor)\n 2. {name}: Name\n 3. {exe-name}: Exe name of real path\n 4. {path}: Full path of real path\n 5. {version}: Version",
"type": "string"
},
"fontFormat": {
@@ -401,7 +421,7 @@
"type": "string"
},
"packagesFormat": {
"description": "Output format of the module `Packages`. See Wiki 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. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {soar}: Number of soar packages\n 43. {nix-all}: Total number of all nix packages\n 44. {flatpak-all}: Total number of all flatpak app packages\n 45. {brew-all}: Total number of all brew packages\n 46. {guix-all}: Total number of all guix packages\n 47. {hpkg-all}: Total number of all hpkg packages",
"description": "Output format of the module `Packages`. See Wiki 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-user}: Number of scoop-user packages\n 21. {scoop-global}: Number of scoop-global packages\n 22. {choco}: Number of choco packages\n 23. {pkgtool}: Number of pkgtool packages\n 24. {paludis}: Number of paludis packages\n 25. {winget}: Number of winget packages\n 26. {opkg}: Number of opkg packages\n 27. {am-system}: Number of am-system packages\n 28. {sorcery}: Number of sorcery packages\n 29. {lpkg}: Number of lpkg packages\n 30. {lpkgbuild}: Number of lpkgbuild packages\n 31. {guix-system}: Number of guix-system packages\n 32. {guix-user}: Number of guix-user packages\n 33. {guix-home}: Number of guix-home packages\n 34. {linglong}: Number of linglong packages\n 35. {pacstall}: Number of pacstall packages\n 36. {mport}: Number of mport packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {soar}: Number of soar packages\n 43. {nix-all}: Total number of all nix packages\n 44. {flatpak-all}: Total number of all flatpak app packages\n 45. {brew-all}: Total number of all brew packages\n 46. {guix-all}: Total number of all guix packages\n 47. {hpkg-all}: Total number of all hpkg packages",
"type": "string"
},
"physicaldiskFormat": {
@@ -469,15 +489,15 @@
"type": "string"
},
"uptimeFormat": {
"description": "Output format of the module `Uptime`. See Wiki for formatting syntax\n 1. {days}: Days after boot\n 2. {hours}: Hours after boot\n 3. {minutes}: Minutes after boot\n 4. {seconds}: Seconds after boot\n 5. {milliseconds}: Milliseconds after boot\n 6. {boot-time}: Boot time in local timezone\n 7. {years}: Years integer after boot\n 8. {days-of-year}: Days of year after boot\n 9. {years-fraction}: Years fraction after boot",
"description": "Output format of the module `Uptime`. See Wiki for formatting syntax\n 1. {days}: Days after boot\n 2. {hours}: Hours after boot\n 3. {minutes}: Minutes after boot\n 4. {seconds}: Seconds after boot\n 5. {milliseconds}: Milliseconds after boot\n 6. {boot-time}: Boot time in local timezone\n 7. {years}: Years integer after boot\n 8. {days-of-year}: Days of year after boot\n 9. {years-fraction}: Years fraction after boot\n 10. {formatted}: Formatted uptime",
"type": "string"
},
"usersFormat": {
"description": "Output format of the module `Users`. See Wiki for formatting syntax\n 1. {name}: User name\n 2. {host-name}: Host name\n 3. {session}: Session name\n 4. {client-ip}: Client IP\n 5. {login-time}: Login Time in local timezone\n 6. {days}: Days after login\n 7. {hours}: Hours after login\n 8. {minutes}: Minutes after login\n 9. {seconds}: Seconds after login\n 10. {milliseconds}: Milliseconds after login\n 11. {years}: Years integer after login\n 12. {days-of-year}: Days of year after login\n 13. {years-fraction}: Years fraction after login",
"description": "Output format of the module `Users`. See Wiki for formatting syntax\n 1. {name}: User name\n 2. {host-name}: Host name\n 3. {session-name}: Session name\n 4. {client-ip}: Client IP\n 5. {login-time}: Login Time in local timezone\n 6. {days}: Days after login\n 7. {hours}: Hours after login\n 8. {minutes}: Minutes after login\n 9. {seconds}: Seconds after login\n 10. {milliseconds}: Milliseconds after login\n 11. {years}: Years integer after login\n 12. {days-of-year}: Days of year after login\n 13. {years-fraction}: Years fraction after login",
"type": "string"
},
"versionFormat": {
"description": "Output format of the module `Version`. See Wiki for formatting syntax\n 1. {name}: Project name\n 2. {version}: Version\n 3. {version-tweak}: Version tweak\n 4. {build-type}: Build type (debug or release)\n 5. {sysname}: System name\n 6. {arch}: Architecture\n 7. {cmake-built-type}: CMake build type when compiling (Debug, Release, RelWithDebInfo, MinSizeRel)\n 8. {compile-time}: Date time when compiling\n 9. {compiler}: Compiler used when compiling\n 10. {libc}: Libc used when compiling",
"description": "Output format of the module `Version`. See Wiki for formatting syntax\n 1. {project-name}: Project name\n 2. {version}: Version\n 3. {version-tweak}: Version tweak\n 4. {build-type}: Build type (debug or release)\n 5. {sysname}: System name\n 6. {arch}: Architecture\n 7. {cmake-built-type}: CMake build type when compiling (Debug, Release, RelWithDebInfo, MinSizeRel)\n 8. {compile-time}: Date time when compiling\n 9. {compiler}: Compiler used when compiling\n 10. {libc}: Libc used when compiling",
"type": "string"
},
"vulkanFormat": {
@@ -921,6 +941,9 @@
"minimum": 0,
"maximum": 9,
"default": 2
},
"spaceBeforeUnit": {
"$ref": "#/$defs/spaceBeforeUnit"
}
}
},
@@ -963,6 +986,9 @@
"default": "light_red"
}
}
},
"spaceBeforeUnit": {
"$ref": "#/$defs/spaceBeforeUnit"
}
}
},
@@ -1035,6 +1061,15 @@
"default": "light_red"
}
}
},
"spaceBeforeUnit": {
"$ref": "#/$defs/spaceBeforeUnit"
},
"width": {
"type": "integer",
"description": "Set the width of the percentage number, in number of characters",
"minimum": 0,
"default": 0
}
}
},
@@ -1049,6 +1084,23 @@
"minimum": -1,
"maximum": 9,
"default": 2
},
"spaceBeforeUnit": {
"$ref": "#/$defs/spaceBeforeUnit"
}
}
},
"duration": {
"type": "object",
"description": "Set how duration values should be displayed",
"properties": {
"abbreviation": {
"type": "boolean",
"description": "Set whether to abbreviate duration values\nIf true, the output will be in the form of \"1h 2m\" instead of \"1 hour, 2 mins\"",
"default": false
},
"spaceBeforeUnit": {
"$ref": "#/$defs/spaceBeforeUnit"
}
}
},
@@ -1959,7 +2011,8 @@
},
"hideFolders": {
"type": "string",
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output\nDefault: /efi:/boot:/boot/efi"
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output",
"default": "/efi:/boot:/boot/efi:/boot/firmware"
},
"hideFS": {
"type": "string",
+85 -24
View File
@@ -6,11 +6,13 @@
"keys": "blue"
},
"separator": "",
// Constants are reusable strings referenced by {$1}, {$2}, etc.
// These contain ANSI escape codes for cursor positioning
"constants": [
"──────────────────────────────────────────────",
"\u001b[47D",
"\u001b[47C",
"\u001b[46C"
"──────────────────────────────────────────────", // {$1} - horizontal line for borders
"\u001b[47D", // {$2} - move cursor left 47 columns
"\u001b[47C", // {$3} - move cursor right 47 columns
"\u001b[46C" // {$4} - move cursor right 46 columns
],
"brightColor": false
},
@@ -22,6 +24,24 @@
},
{
"type": "os",
// Key format breakdown for OS module:
// "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
//
// │ - Left border of key block
// {icon} - OS icon (defined internally by fastfetch)
// \u001b[s - ANSI escape: save cursor position (ESC[s)
// {sysname} - Format variable: system name (e.g., "Linux", "Darwin")
// \u001b[u - ANSI escape: restore cursor to saved position (ESC[u)
// Necessary because the length of `{sysname}` differs between different platforms
// \u001b[10C - ANSI escape: move cursor right 10 columns (ESC[10C)
// │ - Right border of key block (always 10 columns from left border)
// {$3} - Reference to constants[2]: move cursor right 47 columns
// │ - Right border of value block
// {$2} - Reference to constants[1]: move cursor left 47 columns
//
// This creates a fixed-width layout where the key block is exactly 10 columns wide,
// regardless of the actual content length. The cursor manipulation ensures proper
// alignment for the table-like structure.
"key": "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
},
{
@@ -34,7 +54,7 @@
"key": "│ {icon} Locale │{$3}│{$2}"
},
// Hardware
// Hardware section with cyan color theme
{
"type": "custom",
"key": "│{#cyan}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
@@ -42,6 +62,11 @@
},
{
"type": "chassis",
// Similar structure but with cyan color formatting:
// │{#cyan}│ - Left border with cyan color
// {icon} - Chassis icon
// Chassis - Fixed label text
// │{$4}│{#keys}│{$2} - Positioning and borders for value area
"key": "│{#cyan}│ {icon} Chassis │{$4}│{#keys}│{$2}"
},
{
@@ -76,7 +101,7 @@
"format": ""
},
// Desktop
// Desktop section with green color theme
{
"type": "custom",
"key": "│{#green}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
@@ -106,7 +131,7 @@
"format": ""
},
// Terminal
// Terminal section with yellow color theme
{
"type": "custom",
"key": "│{#yellow}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
@@ -138,7 +163,7 @@
"format": ""
},
// Development
// Development section with red color theme
{
"type": "custom",
"key": "│{#red}┌──────────────┬{$1}┐{#keys}│\u001b[39D",
@@ -146,31 +171,44 @@
},
{
"type": "command",
"keyIcon": "",
"keyIcon": "", // Custom icon override
"key": "│{#red}│ {icon} Rust │{$4}│{#keys}│{$2}",
"text": "rustc --version | cut -d' ' -f2",
"format": "rustc {}"
"text": "rustc --version",
"format": "rustc {~6,13}" // Print 6th to 13th characters (version number)
},
{
"type": "command",
"condition": {
"!system": "Windows" // Posix version
},
"keyIcon": "",
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
"text": "clang --version | head -1 | awk '{print $NF}'",
"format": "clang {}"
},
{
"type": "command",
"condition": {
"system": "Windows" // Windows version
},
"keyIcon": "",
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
"text": "clang --version | findstr version", // Finds the line with "version"
"format": "clang {~-6}" // Prints the last 6 characters (version number)
},
{
"type": "command",
"keyIcon": "",
"key": "│{#red}│ {icon} NodeJS │{$4}│{#keys}│{$2}",
"text": "node --version",
"format": "node {~1}"
"format": "node {~1}" // {~1} removes first character (v)
},
{
"type": "command",
"keyIcon": "",
"key": "│{#red}│ {icon} Go │{$4}│{#keys}│{$2}",
"text": "go version | cut -d' ' -f3",
"format": "go {~2}"
"format": "go {~2}" // {~2} removes first 2 characters (go)
},
{
"type": "command",
@@ -200,7 +238,7 @@
"format": ""
},
// Uptime
// Uptime section with magenta color theme
{
"type": "custom",
"key": "│{#magenta}┌──────────────┬{$1}┐{#keys}│\u001b[36D",
@@ -212,28 +250,28 @@
},
{
"type": "users",
"myselfOnly": true,
"myselfOnly": true, // Only show current user
"keyIcon": "",
"key": "│{#magenta}│ {icon} Login │{$4}│{#keys}│{$2}"
},
{
"condition": {
"condition": { // Conditional module: only show on non-macOS
"!system": "macOS"
},
"type": "disk",
"keyIcon": "",
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
"folders": "/",
"format": "{create-time:10} [{days} days]"
"folders": "/", // Check root filesystem
"format": "{create-time:10} [{days} days]" // Show creation time and age in days
},
{
"condition": {
"condition": { // Conditional module: only show on macOS
"system": "macOS"
},
"type": "disk",
"keyIcon": "",
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
"folders": "/System/Volumes/VM",
"folders": "/System/Volumes/VM", // Work around for APFS on macOS
"format": "{create-time:10} [{days} days]"
},
{
@@ -243,12 +281,35 @@
},
{
"type": "custom",
"key": "└─────────────────{$1}┘",
"key": "└─────────────────{$1}┘", // Bottom border of the entire layout
"format": ""
},
// End
"break",
"colors"
// End with color palette and line break
"break", // Add a blank line
"colors" // Display color palette
]
}
/*
Key Format Structure Explanation:
The key format uses a combination of:
1. Unicode box drawing characters ( ) for borders
2. ANSI escape codes for cursor positioning (\u001b[...)
3. Format variables ({icon}, {sysname}, etc.)
4. Constant references ({$1}, {$2}, etc.)
5. Color formatting ({#color})
ANSI Escape Codes Used:
- \u001b[s - Save cursor position (ESC[s)
- \u001b[u - Restore cursor position (ESC[u)
- \u001b[nC - Move cursor right n columns (ESC[nC)
- \u001b[nD - Move cursor left n columns (ESC[nD)
This creates a table-like layout with fixed column widths and proper alignment,
regardless of the actual content length in each field.
For more ANSI escape code reference, see:
https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#cursor-controls
*/
+87
View File
@@ -0,0 +1,87 @@
#include "duration.h"
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result)
{
const FFOptionsDisplay* options = &instance.config.display;
const char* space = instance.config.display.durationSpaceBeforeUnit != FF_SPACE_BEFORE_UNIT_NEVER ? " " : "";
if(totalSeconds < 60)
{
ffStrbufAppendF(result, options->durationAbbreviation ? "%u%ssec" : "%u%ssecond", (unsigned) totalSeconds, space);
if (totalSeconds != 1)
ffStrbufAppendC(result, 's');
return;
}
uint32_t seconds = (uint32_t) (totalSeconds % 60);
totalSeconds /= 60;
if (seconds >= 30)
totalSeconds++;
uint32_t minutes = (uint32_t) (totalSeconds % 60);
totalSeconds /= 60;
uint32_t hours = (uint32_t) (totalSeconds % 24);
totalSeconds /= 24;
uint32_t days = (uint32_t) totalSeconds;
if(days > 0)
{
if(options->durationAbbreviation)
{
ffStrbufAppendF(result, "%u%sd", days, space);
if(hours > 0 || minutes > 0)
ffStrbufAppendC(result, ' ');
}
else
{
ffStrbufAppendF(result, "%u%sday", days, space);
if(days > 1)
ffStrbufAppendC(result, 's');
if(days >= 100)
ffStrbufAppendS(result, "(!)");
if(hours > 0 || minutes > 0)
ffStrbufAppendS(result, ", ");
}
}
if(hours > 0)
{
if(options->durationAbbreviation)
{
ffStrbufAppendF(result, "%u%sh", hours, space);
if (minutes > 0)
ffStrbufAppendC(result, ' ');
}
else
{
ffStrbufAppendF(result, "%u%shour", hours, space);
if(hours > 1)
ffStrbufAppendC(result, 's');
if(minutes > 0)
ffStrbufAppendS(result, ", ");
}
}
if(minutes > 0)
{
if(options->durationAbbreviation)
{
ffStrbufAppendF(result, "%u%sm", minutes, space);
}
else
{
ffStrbufAppendF(result, "%u%smin", minutes, space);
if(minutes > 1)
ffStrbufAppendC(result, 's');
}
}
}
+3
View File
@@ -0,0 +1,3 @@
#include "fastfetch.h"
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result);
+17
View File
@@ -0,0 +1,17 @@
#include "frequency.h"
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result)
{
if (mhz == 0)
return false;
const FFOptionsDisplay* options = &instance.config.display;
const char* space = options->freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ";
int8_t ndigits = options->freqNdigits;
if (ndigits >= 0)
ffStrbufAppendF(result, "%.*f%sGHz", ndigits, mhz / 1000., space);
else
ffStrbufAppendF(result, "%u%sMHz", (unsigned) mhz, space);
return true;
}
+3
View File
@@ -0,0 +1,3 @@
#include "fastfetch.h"
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result);
+19 -1
View File
@@ -31,6 +31,7 @@ static inline FFNativeFD FFUnixFD2NativeFD(int unixfd)
#endif
}
FF_C_NONNULL(3)
static inline bool ffWriteFDData(FFNativeFD fd, size_t dataSize, const void* data)
{
#ifndef _WIN32
@@ -41,18 +42,22 @@ static inline bool ffWriteFDData(FFNativeFD fd, size_t dataSize, const void* dat
#endif
}
FF_C_NONNULL(2)
static inline bool ffWriteFDBuffer(FFNativeFD fd, const FFstrbuf* content)
{
return ffWriteFDData(fd, content->length, content->chars);
}
FF_C_NONNULL(1, 3)
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
FF_C_NONNULL(1, 2)
static inline bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
{
return ffWriteFileData(fileName, buffer->length, buffer->chars);
}
FF_C_NONNULL(3)
static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data)
{
#ifndef _WIN32
@@ -66,26 +71,32 @@ static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data)
#endif
}
FF_C_NONNULL(1, 3)
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
FF_C_NONNULL(2, 4)
ssize_t ffReadFileDataRelative(FFNativeFD dfd, const char* fileName, size_t dataSize, void* data);
FF_C_NONNULL(2)
bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer);
FF_C_NONNULL(1, 2)
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
FF_C_NONNULL(2, 3)
bool ffAppendFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer);
FF_C_NONNULL(1, 2)
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFileBuffer(fileName, buffer);
}
FF_C_NONNULL(2, 3)
static inline bool ffReadFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFileBufferRelative(dfd, fileName, buffer);
}
//Bit flags, combine with |
typedef enum __attribute__((__packed__)) FFPathType
{
FF_PATHTYPE_FILE = 1 << 0,
@@ -94,6 +105,7 @@ typedef enum __attribute__((__packed__)) FFPathType
FF_PATHTYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFPathType;
FF_C_NONNULL(1)
static inline bool ffPathExists(const char* path, FFPathType pathType)
{
#ifdef _WIN32
@@ -136,11 +148,13 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
return false;
}
FF_C_NONNULL(1, 2)
bool ffPathExpandEnv(const char* in, FFstrbuf* out);
#define FF_IO_TERM_RESP_WAIT_MS 100 // #554
FF_C_SCANF(3, 4)
FF_C_NONNULL(1, 3)
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...);
// Not thread safe!
@@ -157,6 +171,7 @@ static inline void ffUnsuppressIO(bool* suppressed)
void ffListFilesRecursively(const char* path, bool pretty);
FF_C_NONNULL(1)
static inline bool wrapClose(FFNativeFD* pfd)
{
assert(pfd);
@@ -176,6 +191,7 @@ static inline bool wrapClose(FFNativeFD* pfd)
}
#define FF_AUTO_CLOSE_FD __attribute__((__cleanup__(wrapClose)))
FF_C_NONNULL(1)
static inline bool wrapFclose(FILE** pfile)
{
assert(pfile);
@@ -186,6 +202,7 @@ static inline bool wrapFclose(FILE** pfile)
}
#define FF_AUTO_CLOSE_FILE __attribute__((__cleanup__(wrapFclose)))
FF_C_NONNULL(1)
#ifndef _WIN32
static inline bool wrapClosedir(DIR** pdir)
{
@@ -207,6 +224,7 @@ static inline bool wrapClosedir(HANDLE* pdir)
#endif
#define FF_AUTO_CLOSE_DIR __attribute__((__cleanup__(wrapClosedir)))
FF_C_NONNULL(1, 2, 3)
static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char* fileSubpath, FFstrbuf* result)
{
// configDirs is a list of FFstrbufs include the trailing slash
+2 -1
View File
@@ -3,7 +3,8 @@
#ifndef _WIN32
#include <net/if.h>
#else
#define IF_NAMESIZE 0
#include <ws2tcpip.h>
#include <iphlpapi.h>
#endif
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex);
-3
View File
@@ -2,8 +2,5 @@
#include "fastfetch.h"
#ifndef _WIN32
const char* ffNetifGetDefaultRouteIfName();
#endif
uint32_t ffNetifGetDefaultRouteIfIndex();
+28 -6
View File
@@ -4,15 +4,15 @@
#include <ws2tcpip.h> // AF_INET6, IN6_IS_ADDR_UNSPECIFIED
#include <iphlpapi.h>
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
{
PMIB_IPFORWARD_TABLE2 pIpForwardTable = NULL;
DWORD result = GetIpForwardTable2(AF_UNSPEC, &pIpForwardTable);
if (result != NO_ERROR)
if (!NETIO_SUCCESS(GetIpForwardTable2(AF_UNSPEC, &pIpForwardTable)))
return false;
bool foundDefault = false;
uint32_t smallestMetric = UINT32_MAX;
for (ULONG i = 0; i < pIpForwardTable->NumEntries; ++i)
{
@@ -24,9 +24,31 @@ bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char iface[IF_NAMESIZE + 1], uin
(row->DestinationPrefix.Prefix.Ipv6.sin6_family == AF_INET6 &&
IN6_IS_ADDR_UNSPECIFIED(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr))))
{
*ifIndex = row->InterfaceIndex;
foundDefault = true;
break;
MIB_IF_ROW2 ifRow = {
.InterfaceIndex = row->InterfaceIndex,
};
if (NETIO_SUCCESS(GetIfEntry2(&ifRow)) &&
ifRow.OperStatus == IfOperStatusUp)
{
MIB_IPINTERFACE_ROW ipInterfaceRow = {
.Family = (row->DestinationPrefix.Prefix.Ipv4.sin_family == AF_INET) ? AF_INET : AF_INET6,
.InterfaceIndex = row->InterfaceIndex,
};
uint32_t realMetric = row->Metric /* Metric offset */;
if (NETIO_SUCCESS(GetIpInterfaceEntry(&ipInterfaceRow)))
realMetric += ipInterfaceRow.Metric /* Interface metric */;
if (realMetric < smallestMetric)
{
smallestMetric = realMetric;
*ifIndex = row->InterfaceIndex;
if (WideCharToMultiByte(CP_UTF8, 0, ifRow.Alias, -1, iface, IF_NAMESIZE, NULL, NULL) > 0)
iface[IF_NAMESIZE] = '\0';
foundDefault = true;
}
}
}
}
-106
View File
@@ -2,7 +2,6 @@
#include "common/parsing.h"
#include <ctype.h>
#include <inttypes.h>
#ifdef _WIN32
#pragma GCC diagnostic push
@@ -60,56 +59,6 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty)
ffStrbufAppendF(pretty, ".%u", version->patch);
}
static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const char** prefixes)
{
double size = (double) bytes;
uint8_t counter = 0;
while(size >= base && counter < instance.config.display.sizeMaxPrefix && prefixes[counter + 1])
{
size /= base;
counter++;
}
if(counter == 0)
ffStrbufAppendF(result, "%" PRIu64 " %s", bytes, prefixes[0]);
else
ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]);
}
void ffParseSize(uint64_t bytes, FFstrbuf* result)
{
switch (instance.config.display.sizeBinaryPrefix)
{
case FF_SIZE_BINARY_PREFIX_TYPE_IEC:
parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL});
break;
case FF_SIZE_BINARY_PREFIX_TYPE_SI:
parseSize(result, bytes, 1000, (const char*[]) {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL});
break;
case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC:
parseSize(result, bytes, 1024, (const char*[]) {"B", "KB", "MB", "GB", "TB", NULL});
break;
default:
parseSize(result, bytes, 1024, (const char*[]) {"B", NULL});
break;
}
}
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result)
{
if (mhz == 0)
return false;
int8_t ndigits = instance.config.display.freqNdigits;
if (ndigits >= 0)
ffStrbufAppendF(result, "%.*f GHz", ndigits, mhz / 1000.);
else
ffStrbufAppendF(result, "%u MHz", (unsigned) mhz);
return true;
}
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
@@ -190,61 +139,6 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
}
}
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result)
{
if(totalSeconds < 60)
{
ffStrbufAppendF(result, "%u second", (unsigned) totalSeconds);
if (totalSeconds != 1)
ffStrbufAppendC(result, 's');
return;
}
uint32_t seconds = (uint32_t) (totalSeconds % 60);
totalSeconds /= 60;
if (seconds >= 30)
totalSeconds++;
uint32_t minutes = (uint32_t) (totalSeconds % 60);
totalSeconds /= 60;
uint32_t hours = (uint32_t) (totalSeconds % 24);
totalSeconds /= 24;
uint32_t days = (uint32_t) totalSeconds;
if(days > 0)
{
ffStrbufAppendF(result, "%u day", days);
if(days > 1)
ffStrbufAppendC(result, 's');
if(days >= 100)
ffStrbufAppendS(result, "(!)");
if(hours > 0 || minutes > 0)
ffStrbufAppendS(result, ", ");
}
if(hours > 0)
{
ffStrbufAppendF(result, "%u hour", hours);
if(hours > 1)
ffStrbufAppendC(result, 's');
if(minutes > 0)
ffStrbufAppendS(result, ", ");
}
if(minutes > 0)
{
ffStrbufAppendF(result, "%u min", minutes);
if(minutes > 1)
ffStrbufAppendC(result, 's');
}
}
#ifdef _WIN32
#pragma GCC diagnostic pop
#endif
-4
View File
@@ -24,7 +24,3 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
void ffParseSize(uint64_t bytes, FFstrbuf* result);
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result);
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result);
+2 -2
View File
@@ -175,7 +175,6 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConf
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
else
{
@@ -187,7 +186,8 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConf
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
}
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
ffStrbufAppendF(buffer, "%*.*f%s%%", options->percentWidth, options->percentNdigits, percent,
options->percentSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : "");
if (colored && !options->pipe)
{
+42
View File
@@ -0,0 +1,42 @@
#include "size.h"
#include <inttypes.h>
static void appendNum(FFstrbuf* result, uint64_t bytes, uint32_t base, const char** prefixes)
{
const FFOptionsDisplay* options = &instance.config.display;
double size = (double) bytes;
uint8_t counter = 0;
while(size >= base && counter < options->sizeMaxPrefix && prefixes[counter + 1])
{
size /= base;
counter++;
}
const char* space = options->sizeSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ";
if(counter == 0)
ffStrbufAppendF(result, "%" PRIu64 "%s%s", bytes, space, prefixes[0]);
else
ffStrbufAppendF(result, "%.*f%s%s", options->sizeNdigits, size, space, prefixes[counter]);
}
void ffSizeAppendNum(uint64_t bytes, FFstrbuf* result)
{
const FFOptionsDisplay* options = &instance.config.display;
switch (options->sizeBinaryPrefix)
{
case FF_SIZE_BINARY_PREFIX_TYPE_IEC:
appendNum(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL});
break;
case FF_SIZE_BINARY_PREFIX_TYPE_SI:
appendNum(result, bytes, 1000, (const char*[]) {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL});
break;
case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC:
appendNum(result, bytes, 1024, (const char*[]) {"B", "KB", "MB", "GB", "TB", NULL});
break;
default:
appendNum(result, bytes, 1024, (const char*[]) {"B", NULL});
break;
}
}
+3
View File
@@ -0,0 +1,3 @@
#include "fastfetch.h"
void ffSizeAppendNum(uint64_t bytes, FFstrbuf* result);
+6 -3
View File
@@ -41,13 +41,16 @@ void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig confi
{
case FF_TEMPERATURE_UNIT_DEFAULT:
case FF_TEMPERATURE_UNIT_CELSIUS:
ffStrbufAppendF(buffer, "%.*f°C", options->tempNdigits, celsius);
ffStrbufAppendF(buffer, "%.*f%s°C", options->tempNdigits, celsius,
options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : "");
break;
case FF_TEMPERATURE_UNIT_FAHRENHEIT:
ffStrbufAppendF(buffer, "%.*f°F", options->tempNdigits, celsius * 1.8 + 32);
ffStrbufAppendF(buffer, "%.*f%s°F", options->tempNdigits, celsius * 1.8 + 32,
options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : "");
break;
case FF_TEMPERATURE_UNIT_KELVIN:
ffStrbufAppendF(buffer, "%.*f K", options->tempNdigits, celsius + 273.15);
ffStrbufAppendF(buffer, "%.*f%sK", options->tempNdigits, celsius + 273.15,
options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ");
break;
}
+82 -2
View File
@@ -454,7 +454,8 @@
"remark": "Auto-detected based on isatty(1) by default",
"arg": {
"type": "bool",
"optional": true
"optional": true,
"default": false
}
},
{
@@ -500,6 +501,28 @@
"type": "color"
}
},
{
"long": "duration-abbreviation",
"desc": "Specify whether to abbreviate duration values",
"remark": "If true, the output will be in the form of \"1h 2m\" instead of \"1 hour, 2 mins\"",
"arg": {
"type": "bool",
"optional": true,
"default": false
}
},
{
"long": "duration-space-before-unit",
"desc": "Specify whether to put a space before the unit in duration values",
"arg": {
"type": "enum",
"enum": {
"default": "Use the default behavior of the module",
"always": "Always put a space before the unit",
"never": "Never put a space before the unit"
}
}
},
{
"long": "key-width",
"desc": "Align the width of keys to <num> characters",
@@ -623,6 +646,27 @@
"default": "light_red"
}
},
{
"long": "percent-space-before-unit",
"desc": "Specify whether to put a space before the percentage symbol",
"arg": {
"type": "enum",
"enum": {
"default": "Use the default behavior of the module",
"always": "Always put a space before the unit",
"never": "Never put a space before the unit"
}
}
},
{
"long": "percent-width",
"desc": "Specify the width of the percentage number, in number of characters",
"remark": "This option affects only percentage numbers, not bars",
"arg": {
"type": "num",
"default": 0
}
},
{
"long": "bar-char-elapsed",
"desc": "Set the character to use in the elapsed part of percentage bars",
@@ -711,6 +755,18 @@
"default": "YB"
}
},
{
"long": "size-space-before-unit",
"desc": "Specify whether to put a space before the unit",
"arg": {
"type": "enum",
"enum": {
"default": "Use the default behavior of the module",
"always": "Always put a space before the unit",
"never": "Never put a space before the unit"
}
}
},
{
"long": "freq-ndigits",
"desc": "Set the number of digits to keep after the decimal point when printing CPU/GPU frequency in GHz",
@@ -719,6 +775,18 @@
"default": 2
}
},
{
"long": "freq-space-before-unit",
"desc": "Specify whether to put a space before the unit",
"arg": {
"type": "enum",
"enum": {
"default": "Use the default behavior of the module",
"always": "Always put a space before the unit",
"never": "Never put a space before the unit"
}
}
},
{
"long": "fraction-ndigits",
"desc": "Set the number of digits to keep after the decimal point when printing ordinary fraction numbers",
@@ -776,6 +844,18 @@
"type": "color",
"default": "light_red"
}
},
{
"long": "temp-space-before-unit",
"desc": "Specify whether to put a space before the unit",
"arg": {
"type": "enum",
"enum": {
"default": "Use the default behavior of the module",
"always": "Always put a space before the unit",
"never": "Never put a space before the unit"
}
}
}
],
"Module specific": [
@@ -854,7 +934,7 @@
"desc": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output",
"arg": {
"type": "path",
"default": "/efi:/boot:/boot/efi"
"default": "/efi:/boot:/boot/efi:/boot/firmware"
}
},
{
+1 -1
View File
@@ -15,7 +15,7 @@ typedef struct FFBatteryResult
double capacity;
double temperature;
uint32_t cycleCount;
int32_t timeRemaining;
int32_t timeRemaining; // in seconds, -1 if unknown
} FFBatteryResult;
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results);
+61 -71
View File
@@ -100,85 +100,75 @@ static void detectQualcomm(FFCPUResult* cpu)
{
// https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems_on_chips
if (ffStrbufEqualS(&cpu->name, "SM8750-AC"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Elite for Galaxy [SM8750-AC]");
else if (ffStrbufEqualS(&cpu->name, "SM8750-3"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Elite [SM8750-3]");
else if (ffStrbufEqualS(&cpu->name, "SM8750"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Elite [SM8750]");
else if (ffStrbufEqualS(&cpu->name, "SM8635"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8s Gen 3 [SM8635]");
else if (ffStrbufEqualS(&cpu->name, "SM8650-AC"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Gen 3 for Galaxy [SM8650-AC]");
else if (ffStrbufEqualS(&cpu->name, "SM8650"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Gen 3 [SM8650]");
else if (ffStrbufEqualS(&cpu->name, "SM8550-AC"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Gen 2 for Galaxy [SM8550-AC]");
else if (ffStrbufEqualS(&cpu->name, "SM8550"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Gen 2 [SM8550]");
else if (ffStrbufEqualS(&cpu->name, "SM8475"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8+ Gen 1 [SM8475]");
else if (ffStrbufEqualS(&cpu->name, "SM8450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 8 Gen 1 [SM8450]");
uint32_t code = (uint32_t) strtoul(cpu->name.chars + 2, NULL, 10);
const char* name = NULL;
else if (ffStrbufEqualS(&cpu->name, "SM7675"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 7+ Gen 3 [SM7675]");
else if (ffStrbufEqualS(&cpu->name, "SM7635"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 7s Gen 3 [SM7635]");
else if (ffStrbufEqualS(&cpu->name, "SM7550"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 7 Gen 3 [SM7550]");
else if (ffStrbufEqualS(&cpu->name, "SM7475"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 7+ Gen 2 [SM7550]");
else if (ffStrbufEqualS(&cpu->name, "SM7435"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 7s Gen 2 [SM7435]");
else if (ffStrbufEqualS(&cpu->name, "SM7450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 7 Gen 1 [SM7450]");
switch (code)
{
case 8735: name = "8s Gen 4"; break;
case 8750: name = "8 Elite"; break;
case 8635: name = "8s Gen 3"; break;
case 8650: name = "8 Gen 3"; break;
case 8550: name = "8 Gen 2"; break;
case 8475: name = "8+ Gen 1"; break;
case 8450: name = "8 Gen 1"; break;
case 7750: name = "7 Gen 4"; break;
case 7675: name = "7+ Gen 3"; break;
case 7635: name = "7s Gen 3"; break;
case 7550: name = "7 Gen 3"; break;
case 7475: name = "7+ Gen 2"; break;
case 7435: name = "7s Gen 2"; break;
case 7450: name = "7 Gen 1"; break;
case 6650: name = "6 Gen 4"; break;
case 6375: name = "6s Gen 3"; break;
case 6475: name = "6 Gen 3"; break;
case 6115: name = "6s Gen 1"; break;
case 6450: name = "6 Gen 1"; break;
case 4635: name = "4s Gen 2"; break;
case 4450: name = "4 Gen 2"; break;
case 4375: name = "4 Gen 1"; break;
}
else if (ffStrbufEqualS(&cpu->name, "SM6375-AC"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6s Gen 3 [SM6375-AC]");
else if (ffStrbufEqualS(&cpu->name, "SM6475"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6 Gen 3 [SM6475]");
else if (ffStrbufEqualS(&cpu->name, "SM6115"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6s Gen 1 [SM6115]");
else if (ffStrbufEqualS(&cpu->name, "SM6450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6 Gen 1 [SM6450]");
else if (ffStrbufEqualS(&cpu->name, "SM4635"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4s Gen 2 [SM4635]");
else if (ffStrbufEqualS(&cpu->name, "SM4450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 2 [SM4450]");
else if (ffStrbufEqualS(&cpu->name, "SM4375"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 1 [SM4375]");
if (name)
{
char str[32];
ffStrCopy(str, cpu->name.chars, sizeof(str));
ffStrbufSetF(&cpu->name, "Qualcomm Snapdragon %s [%s]", name, str);
return;
}
}
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]");
uint32_t code = (uint32_t) strtoul(cpu->name.chars + 2, NULL, 10);
const char* name = NULL;
switch (code) // The SOC code of MTK Dimensity series is full of mess
{
case 6991: name = "9400"; break;
case 6989:
case 8796: name = "9300"; break;
case 6985: name = "9200"; break;
case 6983:
case 8798: name = "9000"; break;
case 6899: name = "8400"; break;
case 6897:
case 8792: name = "8300"; break;
case 6896: name = "8200"; break;
case 8795: name = "8100"; break;
case 6895: name = "8000"; break;
}
if (name)
{
char str[32];
ffStrCopy(str, cpu->name.chars, sizeof(str));
ffStrbufSetF(&cpu->name, "MediaTek Dimensity %s [%s]", name, str);
return;
}
}
static void detectAndroid(FFCPUResult* cpu)
+1
View File
@@ -67,6 +67,7 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd);
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd);
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd);
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd);
#endif // FF_HAVE_DRM
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
+3
View File
@@ -60,10 +60,13 @@ const char* ffGpuDetectMetal(FFlist* gpus)
else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1])
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
#else // MAC_OS_X_VERSION_10_15
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
if ([device supportsFamily:MTLGPUFamilyMetal4])
ffStrbufSetStatic(&gpu->platformApi, "Metal 4");
else if ([device supportsFamily:MTLGPUFamilyMetal3])
ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
#pragma clang diagnostic pop
else if ([device supportsFamily:MTLGPUFamilyCommon3])
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3");
else if ([device supportsFamily:MTLGPUFamilyCommon2])
+2
View File
@@ -118,6 +118,8 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
ffDrmDetectXe(gpu, fd);
else if (ffStrStartsWith(driverName, "asahi"))
ffDrmDetectAsahi(gpu, fd);
else if (ffStrStartsWith(driverName, "nouveau"))
ffDrmDetectNouveau(gpu, fd);
else if (dev->bustype == DRM_BUS_PCI)
{
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
+24
View File
@@ -13,6 +13,7 @@
#include "intel_drm.h"
#include "asahi_drm.h"
#include <radeon_drm.h>
#include <nouveau_drm.h>
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
{
@@ -343,6 +344,29 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
return "Failed to query Asahi GPU information";
}
#ifndef DRM_IOCTL_NOUVEAU_GETPARAM
#define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam)
#endif
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd)
{
struct drm_nouveau_getparam getparam = { };
getparam.param = NOUVEAU_GETPARAM_FB_SIZE;
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0)
gpu->dedicated.total = getparam.value;
getparam.param = NOUVEAU_GETPARAM_AGP_SIZE;
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0)
gpu->shared.total = getparam.value;
getparam.param = NOUVEAU_GETPARAM_GRAPH_UNITS;
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0 && getparam.value < INT32_MAX)
gpu->coreCount = (int32_t) getparam.value;
return NULL;
}
#endif // FF_HAVE_DRM
#include "gpu_driver_specific.h"
+11 -10
View File
@@ -10,7 +10,7 @@ struct FFIgclData {
FF_LIBRARY_SYMBOL(ctlEnumerateDevices)
FF_LIBRARY_SYMBOL(ctlGetDeviceProperties)
FF_LIBRARY_SYMBOL(ctlEnumTemperatureSensors)
FF_LIBRARY_SYMBOL(ctlTemperatureGetState)
FF_LIBRARY_SYMBOL(ctlTemperatureGetProperties)
FF_LIBRARY_SYMBOL(ctlEnumMemoryModules)
FF_LIBRARY_SYMBOL(ctlMemoryGetProperties)
FF_LIBRARY_SYMBOL(ctlMemoryGetState)
@@ -41,7 +41,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumerateDevices)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlGetDeviceProperties)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumTemperatureSensors)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlTemperatureGetState)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlTemperatureGetProperties)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumMemoryModules)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetProperties)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState)
@@ -204,19 +204,20 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
uint32_t sensorCount = ARRAY_SIZE(sensors);
if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS && sensorCount > 0)
{
double sumValue = 0;
uint32_t availableCount = 0;
for (uint32_t iSensor = 0; iSensor < sensorCount; iSensor++)
{
double value;
if (igclData.ffctlTemperatureGetState(sensors[iSensor], &value) == CTL_RESULT_SUCCESS)
ctl_temp_properties_t props = { .Size = sizeof(props) };
// The official sample code does not set Version
// https://github.com/intel/drivers.gpu.control-library/blob/1bbacbf3814f2fd0d2b930cdf42fad83f3628db9/Samples/Telemetry_Samples/Sample_TelemetryAPP.cpp#L256
if (igclData.ffctlTemperatureGetProperties(sensors[iSensor], &props) == CTL_RESULT_SUCCESS)
{
sumValue += value;
availableCount++;
if (props.type == CTL_TEMP_SENSORS_GPU)
{
*result.temp = props.maxTemperature;
break;
}
}
}
if (availableCount > 0)
*result.temp = sumValue / availableCount;
}
}
+49
View File
@@ -263,6 +263,49 @@ static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey,
#endif
}
static const char* pciDetectNouveauSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
if (options->temp)
{
const uint32_t pciDirLen = pciDir->length;
ffStrbufAppendS(pciDir, "/hwmon/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
if (dirp)
{
struct dirent* entry;
while ((entry = readdir(dirp)))
{
if (entry->d_name[0] == '.') continue;
ffStrbufAppendS(pciDir, entry->d_name);
ffStrbufAppendS(pciDir, "/temp1_input");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
uint64_t value = ffStrbufToUInt(buffer, 0);
if (value > 0) gpu->temperature = (double) value / 1000.0;
}
break;
}
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
}
return NULL;
}
static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
{
#if FF_HAVE_DRM
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open drm device";
return ffDrmDetectNouveau(gpu, fd);
#else
FF_UNUSED(gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
#endif
}
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
{
const uint32_t drmDirPathLength = deviceDir->length;
@@ -369,6 +412,12 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
if (options->driverSpecific && drmKey)
drmDetectIntelSpecific(gpu, drmKey, buffer);
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && ffStrbufEqualS(&gpu->driver, "nouveau"))
{
pciDetectNouveauSpecific(options, gpu, deviceDir, buffer);
if (options->driverSpecific && drmKey)
drmDetectNouveauSpecific(gpu, drmKey, buffer);
}
else
{
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
+22 -2
View File
@@ -120,8 +120,28 @@ typedef struct ctl_temp_handle_t* ctl_temp_handle_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlenumtemperaturesensors
extern ctl_result_t ctlEnumTemperatureSensors(ctl_device_adapter_handle_t hDAhandle, uint32_t* pCount, ctl_temp_handle_t* phTemperature);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctltemperaturegetstate
extern ctl_result_t ctlTemperatureGetState(ctl_temp_handle_t hTemperature, double* pTemperature);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv427ctlTemperatureGetProperties17ctl_temp_handle_tP21ctl_temp_properties_t
typedef enum ctl_temp_sensors_t
{
CTL_TEMP_SENSORS_GLOBAL = 0,
CTL_TEMP_SENSORS_GPU = 1,
CTL_TEMP_SENSORS_MEMORY = 2,
CTL_TEMP_SENSORS_GLOBAL_MIN = 3,
CTL_TEMP_SENSORS_GPU_MIN = 4,
CTL_TEMP_SENSORS_MEMORY_MIN = 5,
CTL_TEMP_SENSORS_MAX
} ctl_temp_sensors_t;
typedef struct _ctl_temp_properties_t
{
uint32_t Size;
uint8_t Version;
ctl_temp_sensors_t type;
double maxTemperature;
} ctl_temp_properties_t;
extern ctl_result_t ctlTemperatureGetProperties(ctl_temp_handle_t hTemperature, ctl_temp_properties_t* pTemperature);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctlEnumMemoryModules27ctl_device_adapter_handle_tP8uint32_tP16ctl_mem_handle_t
typedef struct ctl_mem_handle_t* ctl_mem_handle_t;
+36 -6
View File
@@ -140,18 +140,45 @@ static void detectQtCt(char qver, FFQtResult* result)
// by the same author and qt6ct understands qt5ct in qt6 applications as well.
char file[] = "qtXct/qtXct.conf";
file[2] = file[8] = qver;
FF_STRBUF_AUTO_DESTROY font = ffStrbufCreate();
ffParsePropFileConfigValues(file, 3, (FFpropquery[]) {
{"style=", &result->widgetStyle},
{"icon_theme=", &result->icons},
{"general=", &result->font}
{"general=", &font}
});
if (ffStrbufStartsWithC(&result->font, '@'))
if (ffStrbufStartsWithC(&font, '@'))
{
// See QVariant notes on https://doc.qt.io/qt-5/qsettings.html and
// https://github.com/fastfetch-cli/fastfetch/issues/1053#issuecomment-2197254769
// Thankfully, newer versions use the more common font encoding.
ffStrbufSetNS(&result->font, 5, file);
ffStrbufSetNS(&font, 5, file);
}
else if (qver == '5')
{
// #1864
const char *p = font.chars;
while (*p)
{
if (p[0] == '\\' && p[1] == 'x' && isxdigit(p[2]) && isxdigit(p[3]) && isxdigit(p[4]) && isxdigit(p[5]))
{
uint32_t codepoint = (uint32_t)strtoul((char[]) { p[2], p[3], p[4], p[5], '\0' }, NULL, 16);
ffStrbufAppendUtf32CodePoint(&result->font, codepoint);
p += 6;
}
else
{
ffStrbufAppendC(&result->font, *p++);
}
}
}
else
{
ffStrbufDestroy(&result->font);
ffStrbufInitMove(&result->font, &font);
}
}
@@ -178,14 +205,17 @@ const FFQtResult* ffDetectQt(void)
ffStrbufInit(&result.wallpaper);
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
const char *qplatformtheme = getenv("QT_QPA_PLATFORMTHEME");
if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA))
detectPlasma(&result);
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
detectLXQt(&result);
else if(ffStrSet(qplatformtheme) && (ffStrEquals(qplatformtheme, "qt5ct") || ffStrEquals(qplatformtheme, "qt6ct")))
detectQtCt(qplatformtheme[2], &result);
else
{
const char *qPlatformTheme = getenv("QT_QPA_PLATFORMTHEME");
if(qPlatformTheme && (ffStrEquals(qPlatformTheme, "qt5ct") || ffStrEquals(qPlatformTheme, "qt6ct")))
detectQtCt(qPlatformTheme[2], &result);
}
if(ffStrbufEqualS(&result.widgetStyle, "kvantum") || ffStrbufEqualS(&result.widgetStyle, "kvantum-dark"))
{
+1 -1
View File
@@ -10,7 +10,7 @@ typedef struct FFLocalIpResult
FFstrbuf mac;
FFstrbuf flags;
int32_t mtu;
int32_t speed;
int32_t speed; // in Mbps
bool defaultRoute;
} FFLocalIpResult;
+4 -1
View File
@@ -95,6 +95,9 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
// Iterate through all of the adapters
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
{
if (adapter->OperStatus != IfOperStatusUp)
continue;
bool isDefaultRoute = adapter->IfIndex == defaultRouteIfIndex;
if ((options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) && !isDefaultRoute)
continue;
@@ -170,7 +173,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
{
FFLocalIpResult* result = FF_LIST_GET(FFLocalIpResult, *results, results->length - 1);
if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT)
result->speed = (int32_t) (adapter->ReceiveLinkSpeed / 1000);
result->speed = (int32_t) (adapter->ReceiveLinkSpeed / 1000000);
if (options->showType & FF_LOCALIP_TYPE_MTU_BIT)
result->mtu = (int32_t) adapter->Mtu;
if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT)
+2 -2
View File
@@ -36,9 +36,9 @@ typedef struct FFPackagesResult
uint32_t pkg;
uint32_t pkgsrc;
uint32_t pkgtool;
uint32_t qi;
uint32_t rpm;
uint32_t scoop;
uint32_t scoopUser;
uint32_t scoopGlobal;
uint32_t snap;
uint32_t soar;
uint32_t sorcery;
+26 -3
View File
@@ -519,6 +519,31 @@ static inline uint32_t getFlatpakRuntimePackages(FFstrbuf* baseDir)
return num_elements;
}
static inline uint32_t getFlatpakAppPackages(FFstrbuf* baseDir)
{
ffStrbufAppendS(baseDir, "app/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
if (dirp == NULL)
return 0;
uint32_t appDirLength = baseDir->length;
uint32_t num_elements = 0;
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL)
{
if(entry->d_type == DT_DIR && entry->d_name[0] != '.')
{
ffStrbufAppendS(baseDir, entry->d_name);
ffStrbufAppendS(baseDir, "/current");
if (ffPathExists(baseDir->chars, FF_PATHTYPE_ANY)) // Exclude deleted apps, #1856
++num_elements;
ffStrbufSubstrBefore(baseDir, appDirLength);
}
}
return num_elements;
}
static uint32_t getFlatpakPackages(FFstrbuf* baseDir, const char* dirname)
{
uint32_t num_elements = 0;
@@ -527,8 +552,7 @@ static uint32_t getFlatpakPackages(FFstrbuf* baseDir, const char* dirname)
ffStrbufAppendS(baseDir, "/flatpak/");
uint32_t flatpakDirLength = baseDir->length;
ffStrbufAppendS(baseDir, "app");
num_elements += ffPackagesGetNumElements(baseDir->chars, true);
num_elements += getFlatpakAppPackages(baseDir);
ffStrbufSubstrBefore(baseDir, flatpakDirLength);
num_elements += getFlatpakRuntimePackages(baseDir);
@@ -576,7 +600,6 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
}
if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", true);
if (!(options->disabled & FF_PACKAGES_FLAG_PACSTALL_BIT)) packageCounts->pacstall += getNumElements(baseDir, "/var/lib/pacstall/metadata", false);
if (!(options->disabled & FF_PACKAGES_FLAG_QI_BIT)) packageCounts->qi += getNumStrings(baseDir, "/var/qi/installed_packages.list", "\n", "qi");
if (!(options->disabled & FF_PACKAGES_FLAG_PISI_BIT)) packageCounts->pisi += getNumElements(baseDir, "/var/lib/pisi/package", true);
if (!(options->disabled & FF_PACKAGES_FLAG_PKGSRC_BIT)) packageCounts->pkgsrc += getNumElements(baseDir, "/usr/pkg/pkgdb", DT_DIR);
}
+39 -7
View File
@@ -1,6 +1,7 @@
#include "packages.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include "util/path.h"
#include <handleapi.h>
#include <fileapi.h>
@@ -33,22 +34,53 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix *
return counter;
}
static inline void wrapYyjsonFree(yyjson_doc** doc)
{
assert(doc);
if (*doc)
yyjson_doc_free(*doc);
}
static void detectScoop(FFPackagesResult* result)
{
FF_STRBUF_AUTO_DESTROY scoopPath = ffStrbufCreateA(MAX_PATH + 3);
ffStrbufAppendS(&scoopPath, instance.state.platform.homeDir.chars);
ffStrbufAppendS(&scoopPath, ".config/scoop/config.json");
const char* scoopEnv = getenv("SCOOP");
if(ffStrSet(scoopEnv))
yyjson_val* root = NULL;
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_file(scoopPath.chars, 0, NULL, NULL);
if (doc)
{
ffStrbufAppendS(&scoopPath, scoopEnv);
root = yyjson_doc_get_root(doc);
if (!yyjson_is_obj(root)) root = NULL;
}
{
ffStrbufClear(&scoopPath);
if (root)
ffStrbufSetS(&scoopPath, yyjson_get_str(yyjson_obj_get(root, "root_path")));
if (scoopPath.length == 0)
{
ffStrbufSet(&scoopPath, &instance.state.platform.homeDir);
ffStrbufAppendS(&scoopPath, "/scoop");
}
ffStrbufAppendS(&scoopPath, "/apps/*");
result->scoopUser = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
}
else
{
ffStrbufAppendS(&scoopPath, instance.state.platform.homeDir.chars);
ffStrbufAppendS(&scoopPath, "/scoop/apps/*");
ffStrbufClear(&scoopPath);
if (root)
ffStrbufSetS(&scoopPath, yyjson_get_str(yyjson_obj_get(root, "global_path")));
if (scoopPath.length == 0)
{
ffStrbufSetS(&scoopPath, getenv("ProgramData"));
ffStrbufAppendS(&scoopPath, "/scoop");
}
ffStrbufAppendS(&scoopPath, "/apps/*");
result->scoopGlobal = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
}
result->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
}
static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result)
File diff suppressed because one or more lines are too long
+31 -4
View File
@@ -554,21 +554,48 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result)
item->conn.channel = 0;
item->conn.frequency = 0;
char operstate;
ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name);
if (!ffAppendFileBuffer(buffer.chars, &item->inf.status))
if (!ffReadFileData(buffer.chars, 1, &operstate))
{
FF_DEBUG("Failed to read operstate file");
continue;
}
ffStrbufTrimRightSpace(&item->inf.status);
FF_DEBUG("Interface status: %s", item->inf.status.chars);
if (!ffStrbufEqualS(&item->inf.status, "up"))
FF_DEBUG("Connection status: %c", operstate);
if (operstate != 'u')
{
FF_DEBUG("Skipping interface as it's not up");
ffStrbufSetStatic(&item->conn.status, "disconnected");
ffStrbufSetF(&buffer, "/sys/class/net/%s/flags", i->if_name);
char flags[16];
ssize_t len = ffReadFileData(buffer.chars, sizeof(flags), flags);
if (len <= 0)
{
FF_DEBUG("Failed to read flags file");
ffStrbufSetStatic(&item->inf.status, "unknown");
continue;
}
flags[len] = '\0';
FF_DEBUG("Interface flags: %s", flags);
unsigned flagsVal = (unsigned) strtoul(flags, NULL, 16);
if (flagsVal & IFF_UP)
{
ffStrbufSetStatic(&item->inf.status, "up");
FF_DEBUG("Interface is up but not connected");
}
else
{
ffStrbufSetStatic(&item->inf.status, "down");
FF_DEBUG("Interface is down");
}
continue;
}
ffStrbufSetStatic(&item->inf.status, "up");
FF_DEBUG("Trying to detect wifi with iw");
if (detectWifiWithIw(item, &buffer) != NULL)
{
+26
View File
@@ -255,6 +255,29 @@ static const char* getOpenbox(FFstrbuf* result)
return "Failed to run command `openbox --version`";
}
static const char* getLabwc(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("labwc", &path);
if (error) return "Failed to find labwc executable path";
ffBinaryExtractStrings(path.chars, extractCommonWmVersion, result, (uint32_t) strlen("0.0.0"));
if (result->length > 0) return NULL;
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // labwc 0.9.0 (+xwayland +nls +rsvg +libsfdo)
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufSubstrBeforeFirstC(result, ' ');
return NULL;
}
return "Failed to run command `labwc --version`";
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
@@ -281,5 +304,8 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE
if (ffStrbufEqualS(wmName, "Openbox"))
return getOpenbox(result);
if (ffStrbufEqualS(wmName, "labwc"))
return getLabwc(result);
return "Unsupported WM";
}
+14
View File
@@ -0,0 +1,14 @@
⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷
⣿⡇ ⢸⣿
⣿⡇ ⢀⣀ ⣀⡀ ⢸⣿
⣿⣇ ⠸⣿⣄ ⣠⣿⠇ ⣸⣿
⢹⣿⡄ ⠙⠻⠿⠿⠟⠋ ⢠⣿⡏
⠹⣿⣦⡀ ⢀⣴⣿⠏
⠈⠛⢿⣶⣤⣄ ⣠⣤⣶⡿⠛⠁
$2 ⣠⣴⡿⠿⠛ ⠛⠿⢿⣦⣄
⣠⣾⠟⠉ ⠉⠻⣷⣄
⢰⣿⠏ ⢀⣤⣶⣶⣤⡀ ⠹⣿⡆
⣿⡟ ⢰⣿⠏⠁⠈⠹⣿⡆ ⢿⣿
⣿⡇ ⠈⠋ ⠙⠁ ⢸⣿
⣿⡇ ⢸⣿
⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿
-10
View File
@@ -1,10 +0,0 @@
#-----------------------------------------------------------------------#
|#SSSSSSSS\*SS\****SS\**SSSSSS\**SS\*******SSSSSS\*SS\***SS\*SS\***SS\*#|
|#SS**_____|SS*|***SS*|SS**__SS\*SS*|******\_SS**_|SSS\**SS*|SS*|**SS*|#|
|#SS*|******SS*|***SS*|SS*/**SS*|SS*|********SS*|**SSSS\*SS*|\SS\*SS**|#|
|#SSSSS\****\SS\**SS**|SS*|**SS*|SS*|********SS*|**SS*SS\SS*|*\SSSS**/*#|
|#SS**__|****\SS\SS**/*SS*|**SS*|SS*|********SS*|**SS*\SSSS*|*SS**SS<**#|
|#SS*|********\SSS**/**SS*|**SS*|SS*|********SS*|**SS*|\SSS*|SS**/\SS\*#|
|#SSSSSSSS\****\S**/****SSSSSS**|SSSSSSSS\*SSSSSS\*SS*|*\SS*|SS*/**SS*|#|
|#\________|****\_/*****\______/*\________|\______|\__|**\__|\__|**\__|#|
#-----------------------------------------------------------------------#
+9 -10
View File
@@ -30,6 +30,15 @@ static const FFlogo A[] = {
FF_COLOR_FG_CYAN,
},
},
// Aeon
{
.names = {"Aeon"},
.lines = FASTFETCH_DATATEXT_LOGO_AEON,
.colors = {
FF_COLOR_FG_256 "36",
FF_COLOR_FG_256 "36",
},
},
// Afterglow
{
.names = {"Afterglow"},
@@ -1614,16 +1623,6 @@ static const FFlogo E[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_DEFAULT,
},
// Evolinx
{
.names = {"Evolinx"},
.lines = FASTFETCH_DATATEXT_LOGO_EVOLINX,
.colors = {
FF_COLOR_FG_BLUE,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// EvolutionOS
{
.names = {"EvolutionOS"},
+9 -2
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/percent.h"
#include "common/parsing.h"
#include "common/duration.h"
#include "common/temps.h"
#include "detection/battery/battery.h"
#include "modules/battery/battery.h"
@@ -59,7 +59,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
if(str.length > 0)
ffStrbufAppendS(&str, " (");
ffParseDuration((uint32_t) result->timeRemaining, &str);
ffDurationAppendNum((uint32_t) result->timeRemaining, &str);
ffStrbufAppendS(&str, " remaining)");
}
}
@@ -101,6 +101,9 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
ffPercentAppendBar(&capacityBar, result->capacity, options->percent, &options->moduleArgs);
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
ffTempsAppendNum(result->temperature, &tempStr, options->tempConfig, &options->moduleArgs);
FF_STRBUF_AUTO_DESTROY timeStr = ffStrbufCreate();
if (result->timeRemaining > 0)
ffDurationAppendNum((uint32_t) result->timeRemaining, &timeStr);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
FF_FORMAT_ARG(result->manufacturer, "manufacturer"),
@@ -117,6 +120,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
FF_FORMAT_ARG(hours, "time-hours"),
FF_FORMAT_ARG(minutes, "time-minutes"),
FF_FORMAT_ARG(seconds, "time-seconds"),
FF_FORMAT_ARG(timeStr, "time-formatted"),
}));
}
}
@@ -254,6 +258,8 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc,
yyjson_mut_obj_add_uint(doc, obj, "cycleCount", battery->cycleCount);
if (battery->timeRemaining > 0)
yyjson_mut_obj_add_int(doc, obj, "timeRemaining", battery->timeRemaining);
else
yyjson_mut_obj_add_null(doc, obj, "timeRemaining");
}
FF_LIST_FOR_EACH(FFBatteryResult, battery, results)
@@ -290,6 +296,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Battery time remaining hours", "time-hours"},
{"Battery time remaining minutes", "time-minutes"},
{"Battery time remaining seconds", "time-seconds"},
{"Battery time remaining (formatted)", "time-formatted"},
}))
};
+6 -5
View File
@@ -1,6 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/percent.h"
#include "common/size.h"
#include "detection/btrfs/btrfs.h"
#include "modules/btrfs/btrfs.h"
#include "util/stringUtils.h"
@@ -34,11 +35,11 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i
}
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
ffParseSize(used, &usedPretty);
ffSizeAppendNum(used, &usedPretty);
FF_STRBUF_AUTO_DESTROY allocatedPretty = ffStrbufCreate();
ffParseSize(allocated, &allocatedPretty);
ffSizeAppendNum(allocated, &allocatedPretty);
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
ffParseSize(total, &totalPretty);
ffSizeAppendNum(total, &totalPretty);
double usedPercentage = total > 0 ? (double) used / (double) total * 100.0 : 0;
double allocatedPercentage = total > 0 ? (double) allocated / (double) total * 100.0 : 0;
@@ -74,9 +75,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i
ffPercentAppendBar(&allocatedPercentageBar, allocatedPercentage, options->percent, &options->moduleArgs);
FF_STRBUF_AUTO_DESTROY nodeSizePretty = ffStrbufCreate();
ffParseSize(result->nodeSize, &nodeSizePretty);
ffSizeAppendNum(result->nodeSize, &nodeSizePretty);
FF_STRBUF_AUTO_DESTROY sectorSizePretty = ffStrbufCreate();
ffParseSize(result->sectorSize, &sectorSizePretty);
ffSizeAppendNum(result->sectorSize, &sectorSizePretty);
FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
FF_FORMAT_ARG(result->name, "name"),
+4 -3
View File
@@ -2,6 +2,7 @@
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/temps.h"
#include "common/frequency.h"
#include "detection/cpu/cpu.h"
#include "modules/cpu/cpu.h"
#include "util/stringUtils.h"
@@ -77,7 +78,7 @@ void ffPrintCPU(FFCPUOptions* options)
if(freq > 0)
{
ffStrbufAppendS(&str, " @ ");
ffParseFrequency(freq, &str);
ffFreqAppendNum(freq, &str);
}
if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET
@@ -91,9 +92,9 @@ void ffPrintCPU(FFCPUOptions* options)
else
{
FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBase, &freqBase);
ffFreqAppendNum(cpu.frequencyBase, &freqBase);
FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate();
ffParseFrequency(cpu.frequencyMax, &freqMax);
ffFreqAppendNum(cpu.frequencyMax, &freqMax);
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs);
+5 -4
View File
@@ -1,5 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/size.h"
#include "detection/cpucache/cpucache.h"
#include "modules/cpucache/cpucache.h"
#include "util/stringUtils.h"
@@ -45,7 +46,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption
ffStrbufAppendS(&buffer, ", ");
if (src->num > 1)
ffStrbufAppendF(&buffer, "%ux", src->num);
ffParseSize(src->size, &buffer);
ffSizeAppendNum(src->size, &buffer);
ffStrbufAppendF(&buffer, " (%c)", typeStr);
sum += src->size * src->num;
@@ -59,7 +60,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption
else
{
FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate();
ffParseSize(sum, &buffer2);
ffSizeAppendNum(sum, &buffer2);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
FF_FORMAT_ARG(buffer, "result"),
FF_FORMAT_ARG(buffer2, "sum"),
@@ -79,7 +80,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio
uint32_t value = 0;
FF_LIST_FOR_EACH(FFCPUCache, src, result->caches[i])
value += src->size * src->num;
ffParseSize(value, &buffer);
ffSizeAppendNum(value, &buffer);
ffStrbufAppendF(&buffer, " (L%u)", i + 1);
sum += value;
}
@@ -92,7 +93,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio
else
{
FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate();
ffParseSize(sum, &buffer2);
ffSizeAppendNum(sum, &buffer2);
FF_PRINT_FORMAT_CHECKED(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
FF_FORMAT_ARG(buffer, "result"),
FF_FORMAT_ARG(buffer2, "sum"),
+3 -3
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/percent.h"
#include "common/size.h"
#include "common/time.h"
#include "detection/disk/disk.h"
#include "modules/disk/disk.h"
@@ -44,10 +44,10 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index
}
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
ffParseSize(disk->bytesUsed, &usedPretty);
ffSizeAppendNum(disk->bytesUsed, &usedPretty);
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
ffParseSize(disk->bytesTotal, &totalPretty);
ffSizeAppendNum(disk->bytesTotal, &totalPretty);
double bytesPercentage = disk->bytesTotal > 0 ? (double) disk->bytesUsed / (double) disk->bytesTotal * 100.0 : 0;
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
+7 -7
View File
@@ -1,6 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/size.h"
#include "detection/diskio/diskio.h"
#include "modules/diskio/diskio.h"
#include "util/stringUtils.h"
@@ -57,22 +57,22 @@ void ffPrintDiskIO(FFDiskIOOptions* options)
{
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
ffParseSize(dev->bytesRead, &buffer);
ffSizeAppendNum(dev->bytesRead, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (R) - ");
ffParseSize(dev->bytesWritten, &buffer);
ffSizeAppendNum(dev->bytesWritten, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (W)");
ffStrbufPutTo(&buffer, stdout);
}
else
{
ffSizeAppendNum(dev->bytesRead, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufClear(&buffer2);
ffParseSize(dev->bytesRead, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffParseSize(dev->bytesWritten, &buffer2);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffSizeAppendNum(dev->bytesWritten, &buffer2);
if (!options->detectTotal) ffStrbufAppendS(&buffer2, "/s");
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){
FF_FORMAT_ARG(buffer, "size-read"),
+7 -4
View File
@@ -1,5 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/size.h"
#include "detection/displayserver/displayserver.h"
#include "modules/display/display.h"
#include "util/stringUtils.h"
@@ -51,10 +52,11 @@ void ffPrintDisplay(FFDisplayOptions* options)
{
if (result->refreshRate > 0)
{
const char* space = instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : "";
if (options->preciseRefreshRate)
ffStrbufAppendF(&buffer, " @ %gHz", result->refreshRate);
ffStrbufAppendF(&buffer, " @ %g%sHz", result->refreshRate, space);
else
ffStrbufAppendF(&buffer, " @ %iHz", (uint32_t) (result->refreshRate + 0.5));
ffStrbufAppendF(&buffer, " @ %i%sHz", (uint32_t) (result->refreshRate + 0.5), space);
}
ffStrbufAppendS(&buffer, ", ");
}
@@ -108,10 +110,11 @@ void ffPrintDisplay(FFDisplayOptions* options)
if(result->refreshRate > 0)
{
const char* space = instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ";
if(options->preciseRefreshRate)
ffStrbufAppendF(&buffer, " @ %g Hz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0);
ffStrbufAppendF(&buffer, " @ %g%sHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0, space);
else
ffStrbufAppendF(&buffer, " @ %i Hz", (uint32_t) (result->refreshRate + 0.5));
ffStrbufAppendF(&buffer, " @ %i%sHz", (uint32_t) (result->refreshRate + 0.5), space);
}
if(
+1 -1
View File
@@ -130,7 +130,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Type (Visual / Editor)", "type"},
{"Name", "name"},
{"Exe name of real path", "exe-name"},
{"Full path of real path", "full-path"},
{"Full path of real path", "path"},
{"Version", "version"},
}))
};
+10 -9
View File
@@ -1,8 +1,9 @@
#include "common/percent.h"
#include "common/parsing.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/temps.h"
#include "common/size.h"
#include "common/frequency.h"
#include "detection/host/host.h"
#include "detection/gpu/gpu.h"
#include "modules/gpu/gpu.h"
@@ -42,7 +43,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
if(gpu->frequency > 0)
{
ffStrbufAppendS(&output, " @ ");
ffParseFrequency(gpu->frequency, &output);
ffFreqAppendNum(gpu->frequency, &output);
}
if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET
@@ -59,10 +60,10 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
{
if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
{
ffParseSize(gpu->dedicated.used, &output);
ffSizeAppendNum(gpu->dedicated.used, &output);
ffStrbufAppendS(&output, " / ");
}
ffParseSize(gpu->dedicated.total, &output);
ffSizeAppendNum(gpu->dedicated.total, &output);
}
if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
{
@@ -94,8 +95,8 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
FF_STRBUF_AUTO_DESTROY dUsed = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY dPercentNum = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY dPercentBar = ffStrbufCreate();
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->dedicated.total, &dTotal);
if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->dedicated.used, &dUsed);
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->dedicated.total, &dTotal);
if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->dedicated.used, &dUsed);
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
{
double percent = (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0;
@@ -109,8 +110,8 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
FF_STRBUF_AUTO_DESTROY sUsed = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY sPercentNum = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY sPercentBar = ffStrbufCreate();
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->shared.total, &sTotal);
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) ffParseSize(gpu->shared.used, &sUsed);
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->shared.total, &sTotal);
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) ffSizeAppendNum(gpu->shared.used, &sUsed);
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET && gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET)
{
double percent = (double) gpu->shared.used / (double) gpu->shared.total * 100.0;
@@ -121,7 +122,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
}
FF_STRBUF_AUTO_DESTROY frequency = ffStrbufCreate();
ffParseFrequency(gpu->frequency, &frequency);
ffFreqAppendNum(gpu->frequency, &frequency);
FF_STRBUF_AUTO_DESTROY coreUsageNum = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY coreUsageBar = ffStrbufCreate();
+2 -1
View File
@@ -1,5 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/size.h"
#include "modules/kernel/kernel.h"
#include "util/stringUtils.h"
@@ -19,7 +20,7 @@ void ffPrintKernel(FFKernelOptions* options)
else
{
FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate();
ffParseSize(info->pageSize, &str);
ffSizeAppendNum(info->pageSize, &str);
FF_PRINT_FORMAT_CHECKED(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
FF_FORMAT_ARG(info->name, "sysname"),
FF_FORMAT_ARG(info->release, "release"),
+55 -50
View File
@@ -33,57 +33,70 @@ static void formatKey(const FFLocalIpOptions* options, FFLocalIpResult* ip, uint
}
}
static void printIp(FFLocalIpResult* ip, bool markDefaultRoute)
static void appendSpeed(FFLocalIpResult* ip, FFstrbuf* strbuf)
{
if (ip->speed >= 1000000)
{
if (instance.config.display.fractionNdigits >= 0)
ffStrbufAppendF(strbuf, "%.*f Tbps", instance.config.display.fractionNdigits, ip->speed / 1000000.0);
else
ffStrbufAppendF(strbuf, "%g Tbps", ip->speed / 1000000.0);
}
else if (ip->speed >= 1000)
{
if (instance.config.display.fractionNdigits >= 0)
ffStrbufAppendF(strbuf, "%.*f Gbps", instance.config.display.fractionNdigits, ip->speed / 1000.0);
else
ffStrbufAppendF(strbuf, "%g Gbps", ip->speed / 1000.0);
}
else
ffStrbufAppendF(strbuf, "%u Mbps", (unsigned) ip->speed);
}
static void printIp(FFLocalIpResult* ip, bool markDefaultRoute, FFstrbuf* buffer)
{
bool flag = false;
if (ip->ipv4.length)
{
ffStrbufWriteTo(&ip->ipv4, stdout);
flag = true;
ffStrbufAppend(buffer, &ip->ipv4);
}
if (ip->ipv6.length)
{
if (flag) putchar(' ');
ffStrbufWriteTo(&ip->ipv6, stdout);
flag = true;
if (buffer->length) ffStrbufAppendC(buffer, ' ');
ffStrbufAppend(buffer, &ip->ipv6);
}
if (ip->mac.length)
{
if (flag)
printf(" (%s)", ip->mac.chars);
if (buffer->length)
ffStrbufAppendF(buffer, " (%s)", ip->mac.chars);
else
ffStrbufWriteTo(&ip->mac, stdout);
flag = true;
ffStrbufAppend(buffer, &ip->mac);
}
if (ip->mtu > 0 || ip->speed > 0)
{
bool flag = buffer->length > 0;
if (flag)
fputs(" [", stdout);
ffStrbufAppendS(buffer, " [");
if (ip->speed > 0)
{
if (ip->speed >= 1000000)
printf("%g Tbps", ip->speed / 1000000.0);
else if (ip->speed >= 1000)
printf("Speed %g Gbps", ip->speed / 1000.0);
else
printf("Speed %u Mbps", (unsigned) ip->speed);
if (ip->mtu > 0)
fputs(" / ", stdout);
ffStrbufAppendS(buffer, "Speed ");
appendSpeed(ip, buffer);
if (ip->mtu > 0)
ffStrbufAppendS(buffer, " / MTU ");
}
if (ip->mtu > 0)
printf("MTU %u", (unsigned) ip->mtu);
putchar(']');
flag = true;
ffStrbufAppendF(buffer, "%u", (unsigned) ip->mtu);
if (flag)
ffStrbufAppendC(buffer, ']');
}
if (ip->flags.length) {
if (flag) fputs(" <", stdout);
ffStrbufWriteTo(&ip->flags, stdout);
putchar('>');
flag = true;
if (ip->flags.length)
{
if (buffer->length) ffStrbufAppendS(buffer, " <");
ffStrbufAppend(buffer, &ip->flags);
ffStrbufAppendC(buffer, '>');
}
if (markDefaultRoute && flag && ip->defaultRoute)
fputs(" *", stdout);
if (markDefaultRoute && ip->defaultRoute)
ffStrbufAppendS(buffer, " *");
}
void ffPrintLocalIp(FFLocalIpOptions* options)
@@ -106,21 +119,20 @@ void ffPrintLocalIp(FFLocalIpOptions* options)
ffListSort(&results, (const void*) sortIps);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT)
{
ffPrintLogoAndKey(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
bool flag = false;
FF_LIST_FOR_EACH(FFLocalIpResult, ip, results)
{
if (flag)
fputs(" - ", stdout);
else
flag = true;
printIp(ip, false);
if (buffer.length)
ffStrbufAppendS(&buffer, " - ");
printIp(ip, false, &buffer);
}
putchar('\n');
ffStrbufPutTo(&buffer, stdout);
ffStrbufClear(&buffer);
}
else
{
@@ -133,21 +145,13 @@ void ffPrintLocalIp(FFLocalIpOptions* options)
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
printIp(ip, !(options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT));
putchar('\n');
printIp(ip, !(options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT), &buffer);
ffStrbufPutTo(&buffer, stdout);
}
else
{
FF_STRBUF_AUTO_DESTROY speedStr = ffStrbufCreate();
if (ip->speed > 0)
{
if (ip->speed >= 1000000)
ffStrbufSetF(&speedStr, "%g Tbps", ip->speed / 1000000.0);
else if (ip->speed >= 1000)
ffStrbufSetF(&speedStr, "%g Gbps", ip->speed / 1000.0);
else
ffStrbufSetF(&speedStr, "%u Mbps", (unsigned) ip->speed);
}
appendSpeed(ip, &buffer);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){
FF_FORMAT_ARG(ip->ipv4, "ipv4"),
FF_FORMAT_ARG(ip->ipv6, "ipv6"),
@@ -155,11 +159,12 @@ void ffPrintLocalIp(FFLocalIpOptions* options)
FF_FORMAT_ARG(ip->name, "ifname"),
FF_FORMAT_ARG(ip->defaultRoute, "is-default-route"),
FF_FORMAT_ARG(ip->mtu, "mtu"),
FF_FORMAT_ARG(speedStr, "speed"),
FF_FORMAT_ARG(buffer, "speed"),
FF_FORMAT_ARG(ip->flags, "flags"),
}));
}
++index;
ffStrbufClear(&buffer);
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/percent.h"
#include "common/size.h"
#include "detection/memory/memory.h"
#include "modules/memory/memory.h"
#include "util/stringUtils.h"
@@ -18,10 +18,10 @@ void ffPrintMemory(FFMemoryOptions* options)
}
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
ffParseSize(storage.bytesUsed, &usedPretty);
ffSizeAppendNum(storage.bytesUsed, &usedPretty);
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
ffParseSize(storage.bytesTotal, &totalPretty);
ffSizeAppendNum(storage.bytesTotal, &totalPretty);
double percentage = storage.bytesTotal == 0
? 0
+5 -5
View File
@@ -1,6 +1,6 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/size.h"
#include "detection/netio/netio.h"
#include "modules/netio/netio.h"
#include "util/stringUtils.h"
@@ -59,11 +59,11 @@ void ffPrintNetIO(FFNetIOOptions* options)
{
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
ffParseSize(inf->rxBytes, &buffer);
ffSizeAppendNum(inf->rxBytes, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (IN) - ");
ffParseSize(inf->txBytes, &buffer);
ffSizeAppendNum(inf->txBytes, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (OUT)");
@@ -74,9 +74,9 @@ void ffPrintNetIO(FFNetIOOptions* options)
else
{
ffStrbufClear(&buffer2);
ffParseSize(inf->rxBytes, &buffer);
ffSizeAppendNum(inf->rxBytes, &buffer);
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffParseSize(inf->txBytes, &buffer2);
ffSizeAppendNum(inf->txBytes, &buffer2);
if (!options->detectTotal) ffStrbufAppendS(&buffer2, "/s");
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){
+4 -5
View File
@@ -34,11 +34,10 @@ typedef enum __attribute__((__packed__)) FFPackagesFlags
FF_PACKAGES_FLAG_LINGLONG_BIT = 1ULL << 24,
FF_PACKAGES_FLAG_PACSTALL_BIT = 1ULL << 25,
FF_PACKAGES_FLAG_MPORT_BIT = 1ULL << 26,
FF_PACKAGES_FLAG_QI_BIT = 1ULL << 27,
FF_PACKAGES_FLAG_PKGSRC_BIT = 1ULL << 28,
FF_PACKAGES_FLAG_HPKG_BIT = 1ULL << 29,
FF_PACKAGES_FLAG_PISI_BIT = 1ULL << 30,
FF_PACKAGES_FLAG_SOAR_BIT = 1ULL << 31,
FF_PACKAGES_FLAG_PKGSRC_BIT = 1ULL << 27,
FF_PACKAGES_FLAG_HPKG_BIT = 1ULL << 28,
FF_PACKAGES_FLAG_PISI_BIT = 1ULL << 29,
FF_PACKAGES_FLAG_SOAR_BIT = 1ULL << 30,
FF_PACKAGES_FLAG_FORCE_UNSIGNED = UINT64_MAX,
} FFPackagesFlags;
static_assert(sizeof(FFPackagesFlags) == sizeof(uint64_t), "");
+16 -15
View File
@@ -23,6 +23,7 @@ void ffPrintPackages(FFPackagesOptions* options)
uint32_t guixAll = counts.guixSystem + counts.guixUser + counts.guixHome;
uint32_t hpkgAll = counts.hpkgSystem + counts.hpkgUser;
uint32_t amAll = counts.amSystem + counts.amUser;
uint32_t scoopAll = counts.scoopUser + counts.scoopGlobal;
if(options->moduleArgs.outputFormat.length == 0)
{
@@ -104,7 +105,15 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE_NAME(brewCask, "brew-cask")
}
FF_PRINT_PACKAGE(macports)
FF_PRINT_PACKAGE(scoop)
if (options->combined)
{
FF_PRINT_PACKAGE_ALL(scoop);
}
else
{
FF_PRINT_PACKAGE_NAME(scoopUser, counts.scoopGlobal ? "scoop-user" : "scoop")
FF_PRINT_PACKAGE_NAME(scoopGlobal, "scoop-global")
}
FF_PRINT_PACKAGE(choco)
FF_PRINT_PACKAGE(pkgtool)
FF_PRINT_PACKAGE(paludis)
@@ -135,7 +144,6 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE(linglong)
FF_PRINT_PACKAGE(pacstall)
FF_PRINT_PACKAGE(mport)
FF_PRINT_PACKAGE(qi)
FF_PRINT_PACKAGE(pisi)
FF_PRINT_PACKAGE(soar)
@@ -163,7 +171,8 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_FORMAT_ARG(counts.brew, "brew"),
FF_FORMAT_ARG(counts.brewCask, "brew-cask"),
FF_FORMAT_ARG(counts.macports, "macports"),
FF_FORMAT_ARG(counts.scoop, "scoop"),
FF_FORMAT_ARG(counts.scoopUser, "scoop-user"),
FF_FORMAT_ARG(counts.scoopGlobal, "scoop-global"),
FF_FORMAT_ARG(counts.choco, "choco"),
FF_FORMAT_ARG(counts.pkgtool, "pkgtool"),
FF_FORMAT_ARG(counts.paludis, "paludis"),
@@ -179,7 +188,6 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_FORMAT_ARG(counts.linglong, "linglong"),
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(counts.pkgsrc, "pkgsrc"),
FF_FORMAT_ARG(counts.hpkgSystem, "hpkg-system"),
@@ -269,9 +277,6 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(PKGSRC)
break;
case 'Q': if (false);
FF_TEST_PACKAGE_NAME(QI)
break;
case 'R': if (false);
FF_TEST_PACKAGE_NAME(RPM)
break;
@@ -395,9 +400,6 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(PKGSRC)
break;
case 'Q': if (false);
FF_TEST_PACKAGE_NAME(QI)
break;
case 'R': if (false);
FF_TEST_PACKAGE_NAME(RPM)
break;
@@ -466,7 +468,6 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(PKGSRC)
FF_TEST_PACKAGE_NAME(QI)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
@@ -528,10 +529,10 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
FF_APPEND_PACKAGE_COUNT(pkg)
FF_APPEND_PACKAGE_COUNT(pkgtool)
FF_APPEND_PACKAGE_COUNT(pkgsrc)
FF_APPEND_PACKAGE_COUNT(qi)
FF_APPEND_PACKAGE_COUNT(macports)
FF_APPEND_PACKAGE_COUNT(rpm)
FF_APPEND_PACKAGE_COUNT(scoop)
FF_APPEND_PACKAGE_COUNT(scoopUser)
FF_APPEND_PACKAGE_COUNT(scoopGlobal)
FF_APPEND_PACKAGE_COUNT(snap)
FF_APPEND_PACKAGE_COUNT(soar)
FF_APPEND_PACKAGE_COUNT(sorcery)
@@ -568,7 +569,8 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Number of brew packages", "brew"},
{"Number of brew-cask packages", "brew-cask"},
{"Number of macports packages", "macports"},
{"Number of scoop packages", "scoop"},
{"Number of scoop-user packages", "scoop-user"},
{"Number of scoop-global packages", "scoop-global"},
{"Number of choco packages", "choco"},
{"Number of pkgtool packages", "pkgtool"},
{"Number of paludis packages", "paludis"},
@@ -584,7 +586,6 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Number of linglong packages", "linglong"},
{"Number of pacstall packages", "pacstall"},
{"Number of mport packages", "mport"},
{"Number of qi packages", "qi"},
{"Number of am-user (aka appman) packages", "am-user"},
{"Number of pkgsrc packages", "pkgsrc"},
{"Number of hpkg-system packages", "hpkg-system"},
+2 -2
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/temps.h"
#include "common/size.h"
#include "detection/physicaldisk/physicaldisk.h"
#include "modules/physicaldisk/physicaldisk.h"
#include "util/stringUtils.h"
@@ -52,7 +52,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options)
{
formatKey(options, dev, result.length == 1 ? 0 : index + 1, &key);
ffStrbufClear(&buffer);
ffParseSize(dev->size, &buffer);
ffSizeAppendNum(dev->size, &buffer);
const char* physicalType = dev->type & FF_PHYSICALDISK_TYPE_HDD
? "HDD"
+2 -2
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/percent.h"
#include "common/size.h"
#include "detection/physicalmemory/physicalmemory.h"
#include "modules/physicalmemory/physicalmemory.h"
#include "util/stringUtils.h"
@@ -32,7 +32,7 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options)
{
++i;
ffStrbufClear(&prettySize);
ffParseSize(device->size, &prettySize);
ffSizeAppendNum(device->size, &prettySize);
if (options->moduleArgs.outputFormat.length == 0)
{
+3 -3
View File
@@ -1,7 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/percent.h"
#include "common/size.h"
#include "detection/swap/swap.h"
#include "modules/swap/swap.h"
#include "util/stringUtils.h"
@@ -28,10 +28,10 @@ void printSwap(FFSwapOptions* options, uint8_t index, FFSwapResult* storage)
}
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
ffParseSize(storage->bytesUsed, &usedPretty);
ffSizeAppendNum(storage->bytesUsed, &usedPretty);
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
ffParseSize(storage->bytesTotal, &totalPretty);
ffSizeAppendNum(storage->bytesTotal, &totalPretty);
double percentage = storage->bytesTotal == 0
? 0
+5 -3
View File
@@ -1,3 +1,4 @@
#include "common/duration.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/time.h"
@@ -18,13 +19,12 @@ void ffPrintUptime(FFUptimeOptions* options)
}
uint64_t uptime = result.uptime;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
ffDurationAppendNum((uptime + 500) / 1000, &buffer);
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
ffParseDuration((uptime + 500) / 1000, &buffer);
ffStrbufPutTo(&buffer, stdout);
}
else
@@ -51,6 +51,7 @@ void ffPrintUptime(FFUptimeOptions* options)
FF_FORMAT_ARG(age.years, "years"),
FF_FORMAT_ARG(age.daysOfYear, "days-of-year"),
FF_FORMAT_ARG(age.yearsFraction, "years-fraction"),
FF_FORMAT_ARG(buffer, "formatted")
}));
}
}
@@ -124,6 +125,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Years integer after boot", "years"},
{"Days of year after boot", "days-of-year"},
{"Years fraction after boot", "years-fraction"},
{"Formatted uptime", "formatted"},
}))
};
+1 -1
View File
@@ -219,7 +219,7 @@ static FFModuleBaseInfo ffModuleInfo = {
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
{"User name", "name"},
{"Host name", "host-name"},
{"Session name", "session"},
{"Session name", "session-name"},
{"Client IP", "client-ip"},
{"Login Time in local timezone", "login-time"},
{"Days after login", "days"},
+1 -1
View File
@@ -120,7 +120,7 @@ static FFModuleBaseInfo ffModuleInfo = {
.generateJsonResult = (void*) ffGenerateVersionJsonResult,
.generateJsonConfig = (void*) ffGenerateVersionJsonConfig,
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
{"Project name", "name"},
{"Project name", "project-name"},
{"Version", "version"},
{"Version tweak", "version-tweak"},
{"Build type (debug or release)", "build-type"},
+4 -1
View File
@@ -74,7 +74,10 @@ void ffPrintWifi(FFWifiOptions* options)
ffStrbufAppend(&buffer, &item->conn.protocol);
}
if (bandStr[0])
ffStrbufAppendF(&buffer, " - %s GHz", bandStr);
{
ffStrbufAppendF(&buffer, " - %s%sGHz", bandStr,
instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ");
}
if(item->conn.security.length)
{
ffStrbufAppendS(&buffer, " - ");
+3 -2
View File
@@ -1,6 +1,7 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/percent.h"
#include "common/size.h"
#include "detection/zpool/zpool.h"
#include "modules/zpool/zpool.h"
#include "util/stringUtils.h"
@@ -26,10 +27,10 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i
}
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
ffParseSize(result->used, &usedPretty);
ffSizeAppendNum(result->used, &usedPretty);
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
ffParseSize(result->total, &totalPretty);
ffSizeAppendNum(result->total, &totalPretty);
double bytesPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0;
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
+146
View File
@@ -78,6 +78,28 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
options->brightColor = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "binaryPrefix"))
return "`display.binaryPrefix` has been renamed to `display.size.binaryPrefix`. Sorry for another break change.";
else if (ffStrEqualsIgnCase(key, "duration"))
{
if (!yyjson_is_obj(val))
return "display.duration must be an object";
yyjson_val* abbreviation = yyjson_obj_get(val, "abbreviation");
if (abbreviation) options->durationAbbreviation = yyjson_get_bool(abbreviation);
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
{
int value;
const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
if (error) return error;
options->durationSpaceBeforeUnit = (FFSpaceBeforeUnitType) value;
}
}
else if (ffStrEqualsIgnCase(key, "size"))
{
if (!yyjson_is_obj(val))
@@ -119,6 +141,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->sizeNdigits = (uint8_t) yyjson_get_uint(ndigits);
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
{
int value;
const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
if (error) return error;
options->sizeSpaceBeforeUnit = (FFSpaceBeforeUnitType) value;
}
}
else if (ffStrEqualsIgnCase(key, "temp"))
{
@@ -162,6 +198,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* red = yyjson_obj_get(color, "red");
if (red) ffOptionParseColor(yyjson_get_str(red), &options->tempColorRed);
}
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
{
int value;
const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
if (error) return error;
options->tempSpaceBeforeUnit = (FFSpaceBeforeUnitType) value;
}
}
else if (ffStrEqualsIgnCase(key, "percent"))
{
@@ -193,6 +243,23 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* red = yyjson_obj_get(color, "red");
if (red) ffOptionParseColor(yyjson_get_str(red), &options->percentColorRed);
}
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
{
int value;
const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
if (error) return error;
options->percentSpaceBeforeUnit = (FFSpaceBeforeUnitType) value;
}
yyjson_val* width = yyjson_obj_get(val, "width");
if (width) options->percentWidth = (uint8_t) yyjson_get_uint(width);
}
else if (ffStrEqualsIgnCase(key, "bar"))
{
@@ -288,6 +355,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->freqNdigits = (int8_t) yyjson_get_int(ndigits);
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
{
int value;
const char* error = ffJsonConfigParseEnum(spaceBeforeUnit, &value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
if (error) return error;
options->freqSpaceBeforeUnit = (FFSpaceBeforeUnitType) value;
}
}
else
return "Unknown display property";
@@ -403,6 +484,23 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
fprintf(stderr, "--binary-prefix has been renamed to --size-binary-prefix\n");
exit(477);
}
else if(ffStrStartsWithIgnCase(key, "--duration-"))
{
const char* subkey = key + strlen("--duration-");
if(ffStrEqualsIgnCase(subkey, "abbreviation"))
options->durationAbbreviation = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(subkey, "space-before-unit"))
{
options->durationSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
}
else
return false;
}
else if(ffStrStartsWithIgnCase(key, "--size-"))
{
const char* subkey = key + strlen("--size-");
@@ -432,6 +530,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
{}
});
}
else if(ffStrEqualsIgnCase(subkey, "space-before-unit"))
{
options->sizeSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
}
else
return false;
}
@@ -460,6 +567,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
ffOptionParseColor(value, &options->tempColorYellow);
else if(ffStrEqualsIgnCase(subkey, "color-red"))
ffOptionParseColor(value, &options->tempColorRed);
else if(ffStrEqualsIgnCase(subkey, "space-before-unit"))
{
options->tempSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
}
else
return false;
}
@@ -476,6 +592,17 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
ffOptionParseColor(value, &options->percentColorYellow);
else if(ffStrEqualsIgnCase(subkey, "color-red"))
ffOptionParseColor(value, &options->percentColorRed);
else if(ffStrEqualsIgnCase(subkey, "space-before-unit"))
{
options->percentSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
}
else if(ffStrEqualsIgnCase(subkey, "width"))
options->percentWidth = (uint8_t) ffOptionParseUInt32(key, value);
else
return false;
}
@@ -504,6 +631,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
const char* subkey = key + strlen("--freq-");
if(ffStrEqualsIgnCase(subkey, "ndigits"))
options->freqNdigits = (int8_t) ffOptionParseInt32(key, value);
else if(ffStrEqualsIgnCase(subkey, "space-before-unit"))
{
options->freqSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always", FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never", FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
}
else
return false;
}
@@ -531,10 +667,13 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options)
options->debugMode = false;
#endif
options->durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->hideCursor = false;
options->sizeBinaryPrefix = FF_SIZE_BINARY_PREFIX_TYPE_IEC;
options->sizeNdigits = 2;
options->sizeMaxPrefix = UINT8_MAX;
options->sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->stat = -1;
options->noBuffer = false;
options->keyWidth = 0;
@@ -546,18 +685,25 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options)
ffStrbufInitStatic(&options->tempColorGreen, FF_COLOR_FG_GREEN);
ffStrbufInitStatic(&options->tempColorYellow, instance.state.terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW);
ffStrbufInitStatic(&options->tempColorRed, instance.state.terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED);
options->tempSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
ffStrbufInitStatic(&options->barCharElapsed, "");
ffStrbufInitStatic(&options->barCharTotal, "-");
ffStrbufInitStatic(&options->barBorderLeft, "[ ");
ffStrbufInitStatic(&options->barBorderRight, " ]");
options->barWidth = 10;
options->durationAbbreviation = false;
options->durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->percentType = 9;
options->percentNdigits = 0;
ffStrbufInitStatic(&options->percentColorGreen, FF_COLOR_FG_GREEN);
ffStrbufInitStatic(&options->percentColorYellow, instance.state.terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW);
ffStrbufInitStatic(&options->percentColorRed, instance.state.terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED);
options->percentSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->percentWidth = 0;
options->freqNdigits = 2;
options->freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->fractionNdigits = -1;
ffListInit(&options->constants, sizeof(FFstrbuf));
+15
View File
@@ -17,6 +17,13 @@ typedef enum __attribute__((__packed__)) FFTemperatureUnit
FF_TEMPERATURE_UNIT_KELVIN,
} FFTemperatureUnit;
typedef enum __attribute__((__packed__)) FFSpaceBeforeUnitType
{
FF_SPACE_BEFORE_UNIT_DEFAULT,
FF_SPACE_BEFORE_UNIT_ALWAYS,
FF_SPACE_BEFORE_UNIT_NEVER,
} FFSpaceBeforeUnitType;
typedef struct FFOptionsDisplay
{
//If one of those is empty, ffLogoPrint will set them
@@ -36,15 +43,19 @@ typedef struct FFOptionsDisplay
bool debugMode;
#endif
bool disableLinewrap;
bool durationAbbreviation;
FFSpaceBeforeUnitType durationSpaceBeforeUnit;
bool hideCursor;
FFSizeBinaryPrefixType sizeBinaryPrefix;
uint8_t sizeNdigits;
uint8_t sizeMaxPrefix;
FFSpaceBeforeUnitType sizeSpaceBeforeUnit;
FFTemperatureUnit tempUnit;
uint8_t tempNdigits;
FFstrbuf tempColorGreen;
FFstrbuf tempColorYellow;
FFstrbuf tempColorRed;
FFSpaceBeforeUnitType tempSpaceBeforeUnit;
FFstrbuf barCharElapsed;
FFstrbuf barCharTotal;
FFstrbuf barBorderLeft;
@@ -55,12 +66,16 @@ typedef struct FFOptionsDisplay
FFstrbuf percentColorGreen;
FFstrbuf percentColorYellow;
FFstrbuf percentColorRed;
FFSpaceBeforeUnitType percentSpaceBeforeUnit;
uint8_t percentWidth;
bool noBuffer;
FFModuleKeyType keyType;
uint16_t keyWidth;
uint16_t keyPaddingLeft;
int8_t freqNdigits;
FFSpaceBeforeUnitType freqSpaceBeforeUnit;
int8_t fractionNdigits;
FFlist constants; // list of FFstrbuf
} FFOptionsDisplay;
+16 -4
View File
@@ -4,22 +4,34 @@
#include <sal.h>
#endif
#if defined(__GNUC__) || defined(__clang__)
#define FF_C_NODISCARD __attribute__((warn_unused_result))
#if defined(__has_attribute) && __has_attribute(__warn_unused_result__)
#define FF_C_NODISCARD __attribute__((__warn_unused_result__))
#elif defined(_MSC_VER)
#define FF_C_NODISCARD _Check_return_
#else
#define FF_C_NODISCARD
#endif
#if defined(__GNUC__) || defined(__clang__)
#if defined(__has_attribute) && __has_attribute(__format__)
#define FF_C_PRINTF(formatStrIndex, argsStartIndex) __attribute__((__format__ (printf, formatStrIndex, argsStartIndex)))
#else
#define FF_C_PRINTF(formatStrIndex, argsStartIndex)
#endif
#if defined(__GNUC__) || defined(__clang__)
#if defined(__has_attribute) && __has_attribute(__format__)
#define FF_C_SCANF(formatStrIndex, argsStartIndex) __attribute__((__format__ (scanf, formatStrIndex, argsStartIndex)))
#else
#define FF_C_SCANF(formatStrIndex, argsStartIndex)
#endif
#if defined(__has_attribute) && __has_attribute(__nonnull__)
#define FF_C_NONNULL(argIndex, ...) __attribute__((__nonnull__(argIndex, ##__VA_ARGS__)))
#else
#define FF_C_NONNULL(argIndex, ...)
#endif
#if defined(__has_attribute) && __has_attribute(__returns_nonnull__)
#define FF_C_RETURNS_NONNULL __attribute__((__returns_nonnull__))
#else
#define FF_C_RETURNS_NONNULL
#endif
+54 -1
View File
@@ -398,7 +398,8 @@ bool ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index)
if(strbuf->allocated == 0)
{
//static string
ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars);
if (index < strbuf->length)
ffStrbufInitNS(strbuf, index, strbuf->chars);
return true;
}
@@ -461,6 +462,26 @@ bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c)
return true;
}
bool ffStrbufSubstr(FFstrbuf* strbuf, uint32_t start, uint32_t end)
{
if (__builtin_expect(start >= end, false))
{
ffStrbufClear(strbuf);
return false;
}
if (__builtin_expect(start == 0, false)) return ffStrbufSubstrBefore(strbuf, end);
if (__builtin_expect(end >= strbuf->length, false)) return ffStrbufSubstrAfter(strbuf, start - 1);
uint32_t len = end - start;
ffStrbufEnsureFixedLengthFree(strbuf, len); // In case of static string
memmove(strbuf->chars, strbuf->chars + start, len);
strbuf->length = len;
strbuf->chars[len] = '\0';
return true;
}
uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c)
{
uint32_t result = 0;
@@ -661,3 +682,35 @@ bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const
return false;
}
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint)
{
if (codepoint <= 0x7F) {
ffStrbufAppendC(strbuf, (char)codepoint);
return 1;
} else if (codepoint <= 0x7FF) {
ffStrbufAppendNS(strbuf, 2, (char[]){
(char) (0xC0 | (codepoint >> 6)),
(char) (0x80 | (codepoint & 0x3F))
});
return 2;
} else if (codepoint <= 0xFFFF) {
ffStrbufAppendNS(strbuf, 3, (char[]){
(char) (0xE0 | (codepoint >> 12)),
(char) (0x80 | ((codepoint >> 6) & 0x3F)),
(char) (0x80 | (codepoint & 0x3F))
});
return 3;
} else if (codepoint <= 0x10FFFF) {
ffStrbufAppendNS(strbuf, 4, (char[]){
(char) (0xF0 | (codepoint >> 18)),
(char) (0x80 | ((codepoint >> 12) & 0x3F)),
(char) (0x80 | ((codepoint >> 6) & 0x3F)),
(char) (0x80 | (codepoint & 0x3F))
});
return 4;
}
ffStrbufAppendS(strbuf, ""); // U+FFFD REPLACEMENT CHARACTER
return 1;
}
+3
View File
@@ -73,6 +73,7 @@ bool ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index); // Not including the
bool ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c);
bool ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str);
bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c);
bool ffStrbufSubstr(FFstrbuf* strbuf, uint32_t start, uint32_t end);
FF_C_NODISCARD uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c);
@@ -95,6 +96,8 @@ void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer);
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint);
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
{
FFstrbuf strbuf;
+51 -2
View File
@@ -1,4 +1,4 @@
#include "common/parsing.h"
#include "common/duration.h"
#include "util/textModifier.h"
#include "fastfetch.h"
@@ -7,7 +7,7 @@
static void verify(uint64_t totalSeconds, const char* expected, int lineNo)
{
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
ffParseDuration(totalSeconds, &result);
ffDurationAppendNum(totalSeconds, &result);
if (!ffStrbufEqualS(&result, expected))
{
fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %llu: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, (unsigned long long) totalSeconds, expected, result.chars);
@@ -66,6 +66,55 @@ int main(void)
VERIFY(60 * 60 * 24 * 100, "100 days(!)");
VERIFY(60 * 60 * 24 * 200, "200 days(!)");
instance.config.display.durationAbbreviation = true;
instance.config.display.durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER;
// Test seconds less than 60
VERIFY(0, "0secs");
VERIFY(1, "1sec");
VERIFY(2, "2secs");
VERIFY(59, "59secs");
// Test minute rounding (when seconds >= 30)
VERIFY(60, "1m");
VERIFY(60 + 29, "1m");
VERIFY(60 + 30, "2m");
// Test only minutes
VERIFY(60 * 2 - 1, "2m");
VERIFY(60 * 2, "2m");
VERIFY(60 * 59 + 29, "59m");
// Test only hours (no minutes)
VERIFY(60 * 59 + 30, "1h");
VERIFY(60 * 60, "1h");
VERIFY(2 * 60 * 60, "2h");
VERIFY(23 * 60 * 60, "23h");
// Test combination of hours and minutes
VERIFY(60 * 60 + 60, "1h 1m");
VERIFY(60 * 60 + 60 * 2, "1h 2m");
VERIFY(60 * 60 * 2 + 60 + 29, "2h 1m");
VERIFY(60 * 60 * 2 + 60 + 30, "2h 2m");
// Test days
VERIFY(60 * 60 * 24, "1d");
VERIFY(60 * 60 * 24 - 1, "1d");
VERIFY(60 * 60 * 24 * 2, "2d");
// Test combination of days and hours
VERIFY(60 * 60 * 24 + 60 * 60, "1d 1h");
VERIFY(60 * 60 * 24 * 2 + 60 * 60, "2d 1h");
VERIFY(60 * 60 * 24 * 2 + 60 * 60 * 2, "2d 2h");
// Test combination of days, hours, and minutes
VERIFY(60 * 60 * 24 + 60 * 60 + 60, "1d 1h 1m");
VERIFY(60 * 60 * 24 * 2 + 60 * 60 + 60 * 2, "2d 1h 2m");
VERIFY(60 * 60 * 24 * 2 + 60 * 2, "2d 2m");
// Test very large number of days
VERIFY(60 * 60 * 24 * 100, "100d");
VERIFY(60 * 60 * 24 * 200, "200d");
//Success
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
}
+55
View File
@@ -665,6 +665,61 @@ int main(void)
VERIFY(ffStrbufMatchSeparatedS(&strbuf, ":abc", ':') == true);
}
{
ffStrbufSetStatic(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 0, 1); // start, end
VERIFY(ffStrbufEqualS(&strbuf, "a"));
ffStrbufSetStatic(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 1, 1);
VERIFY(ffStrbufEqualS(&strbuf, ""));
ffStrbufSetStatic(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 2, 1);
VERIFY(ffStrbufEqualS(&strbuf, ""));
ffStrbufSetStatic(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 2, 3);
VERIFY(ffStrbufEqualS(&strbuf, "c"));
ffStrbufSetStatic(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 0, 3);
VERIFY(ffStrbufEqualS(&strbuf, "abc"));
}
{
ffStrbufSetS(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 0, 1); // start, end
VERIFY(ffStrbufEqualS(&strbuf, "a"));
ffStrbufSetS(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 1, 1);
VERIFY(ffStrbufEqualS(&strbuf, ""));
ffStrbufSetS(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 2, 1);
VERIFY(ffStrbufEqualS(&strbuf, ""));
ffStrbufSetS(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 2, 3);
VERIFY(ffStrbufEqualS(&strbuf, "c"));
ffStrbufSetS(&strbuf, "abc");
ffStrbufSubstr(&strbuf, 0, 3);
VERIFY(ffStrbufEqualS(&strbuf, "abc"));
ffStrbufDestroy(&strbuf);
}
{
ffStrbufAppendUtf32CodePoint(&strbuf, 0x6587);
ffStrbufAppendUtf32CodePoint(&strbuf, 0x6cc9);
ffStrbufAppendUtf32CodePoint(&strbuf, 0x9a7f);
VERIFY(ffStrbufEqualS(&strbuf, u8"文泉驿"));
ffStrbufDestroy(&strbuf);
}
//Success
puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
}