mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ba8a21142f | |||
| eca3625165 | |||
| 677e920dc8 | |||
| 38c0b24daa | |||
| 4e05502d7a | |||
| d0928a63bf | |||
| aa0bbd5aee | |||
| ce554dbdd0 | |||
| a0174e8666 | |||
| 8be419cfd6 | |||
| ca79bae36e | |||
| b1f0248fb3 | |||
| 77dd18466b | |||
| 5bb6e22679 | |||
| 9ea9291ab8 | |||
| 6ec73863ab | |||
| 8c2f93151d | |||
| 71ddc4ffc6 | |||
| 4909d693e3 | |||
| fe76bbe68a | |||
| d1f20822f1 | |||
| 1ed804db52 | |||
| 0e8b9bec2d | |||
| a3182c31cb | |||
| d2f2c76dfc | |||
| 2d1ae1b4c5 | |||
| 316409ecc3 | |||
| f0fc38bcb5 | |||
| e7a6b84107 | |||
| 02c3254961 | |||
| a90e1d7ccf | |||
| 6cdd64ac55 | |||
| aa1201ffb8 | |||
| 9b491c2f49 | |||
| be3e2ba521 | |||
| ccbb9e90ea | |||
| d07fe997a9 | |||
| b60996bcd1 | |||
| 272c0aad9c | |||
| 7566f10bb6 | |||
| 847b76b863 | |||
| 5c0ad030cc |
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result);
|
||||
+19
-1
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2,8 +2,5 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
const char* ffNetifGetDefaultRouteIfName();
|
||||
#endif
|
||||
|
||||
uint32_t ffNetifGetDefaultRouteIfIndex();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffSizeAppendNum(uint64_t bytes, FFstrbuf* result);
|
||||
+6
-3
@@ -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
@@ -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"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷
|
||||
⣿⡇ ⢸⣿
|
||||
⣿⡇ ⢀⣀ ⣀⡀ ⢸⣿
|
||||
⣿⣇ ⠸⣿⣄ ⣠⣿⠇ ⣸⣿
|
||||
⢹⣿⡄ ⠙⠻⠿⠿⠟⠋ ⢠⣿⡏
|
||||
⠹⣿⣦⡀ ⢀⣴⣿⠏
|
||||
⠈⠛⢿⣶⣤⣄ ⣠⣤⣶⡿⠛⠁
|
||||
$2 ⣠⣴⡿⠿⠛ ⠛⠿⢿⣦⣄
|
||||
⣠⣾⠟⠉ ⠉⠻⣷⣄
|
||||
⢰⣿⠏ ⢀⣤⣶⣶⣤⡀ ⠹⣿⡆
|
||||
⣿⡟ ⢰⣿⠏⠁⠈⠹⣿⡆ ⢿⣿
|
||||
⣿⡇ ⠈⠋ ⠙⠁ ⢸⣿
|
||||
⣿⡇ ⢸⣿
|
||||
⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿
|
||||
@@ -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
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
}))
|
||||
};
|
||||
|
||||
|
||||
@@ -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, §orSizePretty);
|
||||
ffSizeAppendNum(result->sectorSize, §orSizePretty);
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(result->name, "name"),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[]){
|
||||
|
||||
@@ -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), "");
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"},
|
||||
}))
|
||||
};
|
||||
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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, " - ");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user