Compare commits

..

130 Commits

Author SHA1 Message Date
Carter Li da0db042fa Merge pull request #897 from fastfetch-cli/dev
Release: 2.11.5
2024-05-07 00:41:44 +08:00
李通洲 ae5732e2a8 Release: v2.11.5 2024-05-07 00:38:08 +08:00
李通洲 1f05a33807 Logo (Builtin): temp fix for openmandriva logo detection
Fix #896
2024-05-07 00:19:07 +08:00
李通洲 f090951abc Doc: remove --os-file completely 2024-05-06 22:48:46 +08:00
Carter Li 855fd6edee Merge pull request #890 from fastfetch-cli/dev
Release v2.11.4
2024-05-06 20:06:58 +08:00
李通洲 d4bd4401a8 Release: v2.11.4 2024-05-06 19:45:45 +08:00
李通洲 689feb39a4 OS (Linux): don't detect debian version on debian derived distros 2024-05-06 18:42:19 +08:00
Carter Li 0f64e2830a OS (Linux): detect pve & armbian 2024-05-06 16:46:27 +08:00
Carter Li 3e24cdc752 CMake: add option CUSTOM_OS_RELEASE_PATH
And remove `--os-file`
2024-05-06 16:25:08 +08:00
李通洲 dc9c285a0b Doc: update README
Who cares how people install a package...

Close #883
2024-05-06 15:56:46 +08:00
李通洲 1d03c9c85e Logo (Builtin): add armbian
Fix #842
2024-05-06 15:22:43 +08:00
李通洲 4eae11df64 Presets: fix neofetch 2024-05-06 15:09:12 +08:00
李通洲 eba13d5485 JsonConfig: fix setting size.ndigits doesn't work
Silly copy & paste error
2024-05-06 15:08:58 +08:00
apocelipes 16b875ef5a Fastfetch: fix memory leaks when passing informative options
Informative options (e.g. "--help", "--list-module") make fastfetch
exit before calling ffDestroyInstance. Using "atexit" to avoid this
kind of leak.
2024-05-06 14:40:27 +08:00
李通洲 366138e1bd CI: try fixing Linux armv7 2024-05-06 14:08:29 +08:00
李通洲 7fe18a5b7c CI: build armv7 package using ubuntu22.04
Hopefully make it usable on RaspberryPi

Fix #884
2024-05-06 09:33:58 +08:00
李通洲 39cd8cfb4c Camera: fix deprecation warning for macOS 14.0 hopefully
Fix #860
2024-05-06 09:25:06 +08:00
李通洲 8b441c85e5 Logo (Builtin): update ubuntu 2024-05-05 23:31:23 +08:00
李通洲 f66e901c44 Presets: remove unsupported format placeholders 2024-05-05 22:12:33 +08:00
李通洲 3815823a20 CMake: enforce glibc version 2024-05-05 21:29:49 +08:00
李通洲 33ff4870dc Fastfetch: enable pipe mode if $NO_COLOR is set 2024-05-05 20:16:43 +08:00
李通洲 479731f076 Custom: don't print ANSI escape code in pipe mode 2024-05-05 20:14:24 +08:00
李通洲 d2f3f47457 Colors: print non-colored blocks in pipe mode 2024-05-05 20:14:24 +08:00
李通洲 5ea89ecba5 Fastfetch: print non-colored logo in pipe mode 2024-05-05 20:14:23 +08:00
Carter Li 865f57bd76 Revert "FFstrbuf: avoid redundant checks (#881)" (#882)
This reverts commit e98e2a3d52.
2024-05-05 18:46:22 +08:00
Nour1248 e98e2a3d52 FFstrbuf: avoid redundant checks (#881) 2024-05-05 18:40:59 +08:00
Carter Li 6bb748869e Terminal (macOS): fix Apple Terminal detection
Fix #878
2024-05-05 13:36:14 +08:00
李通洲 654721b8c5 Doc: remove (kind of) outdated information
Fix #867
2024-05-05 08:39:51 +08:00
Carter Li 0542eac1b9 Doc: metion ANSI 256 colors
Fix #869
2024-05-05 07:33:32 +08:00
apocelipes b9faf8d77f fastfetch: fix #868 (#871)
Fix #868.
2024-05-05 07:10:51 +08:00
Carter Li 61f848146a Merge pull request #862 from fastfetch-cli/dev
Release: v2.11.3
2024-05-04 20:47:54 +08:00
李通洲 4175dfdc3a Doc: update changelog (ci skip) 2024-05-04 20:27:26 +08:00
李通洲 861d9006d7 Release: v2.11.3 2024-05-04 20:11:30 +08:00
李通洲 7ba07bd2e0 Logo (Image): partially revert 71cba24
Images in SSH session and tmux do work for me

Fix #861
2024-05-04 19:43:41 +08:00
李通洲 9fee36a286 Logo (Image): ensure line ending is printed when printing errors 2024-05-04 19:14:45 +08:00
李通洲 2fc9230b29 Disk (Windows): use sub thread to check accessiblity of remote volumes. 2024-05-04 15:15:00 +08:00
李通洲 5fb1286e15 Battery (Windows): simplify code 2024-05-04 12:11:42 +08:00
李通洲 a4cace4765 CMake: add CUSTOM_AMDGPU_IDS_PATH 2024-05-04 10:06:49 +08:00
李通洲 c6d2467a83 Merge remote-tracking branch 'upstream/master' into dev 2024-05-04 10:06:40 +08:00
AxeldeWater db0d38202e Update README.md again for same reason different location (#857)
Oversaw a place where it wasn't updated either
2024-05-04 07:13:38 +08:00
AxeldeWater 9fbb23b135 Update README.md about installing fastfetch on Debian/Ubuntu (#856)
Apparently the file naming standard was changed over time but this was not updated in the README
2024-05-04 00:00:44 +08:00
李通洲 3a990e495b PhysicalDisk: fix temp output in custom formation
I hate `void *`
2024-05-03 20:48:51 +08:00
李通洲 648530ee8f PhysicalDisk: fix doubled output in custom formation
Fix #852
2024-05-03 20:42:39 +08:00
Carter Li b12a59cdaf Merge pull request #851 from fastfetch-cli/dev
Release: v2.11.2
2024-05-03 14:36:04 +08:00
李通洲 83c1fe26e6 Doc: update changelog 2024-05-03 14:14:13 +08:00
李通洲 217f98a36c Global: tidy json result formats 2024-05-03 13:56:19 +08:00
李通洲 1011e21ba8 Processing: trim \r on Windows 2024-05-03 13:46:28 +08:00
李通洲 08c6a6e4cb OS (macOS): don't print build id
Remove special handling
2024-05-03 13:20:23 +08:00
李通洲 5e9fcaf7ca OS (Linux): don't use rolling as os version 2024-05-03 13:09:14 +08:00
李通洲 8b838cef61 OS (Linux): fix name detection for MX
Fix #847
2024-05-03 12:57:51 +08:00
李通洲 22d9d8e196 OS (Linux): fix OS detection for MX Linux (2nd attempt)
Ref: #847
2024-05-03 11:28:59 +08:00
李通洲 a789b8330a Doc: update logo_request.md 2024-05-03 10:10:13 +08:00
李通洲 903ecf37f7 Chore: silience some warnings 2024-05-03 10:07:16 +08:00
李通洲 c4a876f6aa OS (Linux): Prioritize lsb-release over os-release
Fix #847
2024-05-03 10:00:18 +08:00
李通洲 82285ebeb4 Release: 2.11.2 2024-05-03 10:00:18 +08:00
李通洲 36dadcdc7f Logo (Builtin): add MX2 & fix mx distro detection
Fix: #847
2024-05-03 09:11:59 +08:00
李通洲 030c05429a Logo (Builtin): add missing FF_LOGO_LINE_TYPE_SMALL_BIT flags 2024-05-03 09:11:59 +08:00
李通洲 a462a12370 Logo (Builtin): fix distro name of DraugerOS 2024-05-03 09:11:59 +08:00
李通洲 b386365d95 Logo (Builtin): fix ascii file name 2024-05-03 09:11:59 +08:00
李通洲 158db9d7c7 Logo (Builtin): add KernelOS
Fix #848
2024-05-03 09:11:59 +08:00
李通洲 407bfa8c95 Shell: don't try detecting version of raw sh shell
Fix #849
2024-05-03 09:11:59 +08:00
李通洲 1449290e9e GPU (Linux): check NULL returned by opendir
Fix #845
2024-05-03 09:11:59 +08:00
李通洲 4c0ea7354d Logo (Image): only print error if --show-error is specified 2024-05-03 09:11:59 +08:00
李通洲 71cba2451a Logo: disable image logos in ssh and tmux sessions 2024-05-03 01:10:04 +08:00
李通洲 ef3b5df048 Doc: update man page 2024-05-03 01:10:04 +08:00
Juan 3e98034e55 Packages (Linux): check xdg state home for nix user packages (#844)
Check $XDG_STATE_HOME/nix/profile if ~/.nix-profile is not found as addressed in #837.

Fix #837
2024-05-02 22:55:50 +08:00
李通洲 1c89101522 Doc: update changelog 2024-05-02 20:45:46 +08:00
Carter Li 757e6271ff Merge pull request #840 from fastfetch-cli/dev
Release: v2.11.1
2024-05-02 20:23:35 +08:00
李通洲 c5c846aa22 CI: try build for Linux armv7 2024-05-02 20:03:40 +08:00
李通洲 23a59a15ec Release: v2.11.1 2024-05-02 19:48:17 +08:00
李通洲 4798c619d0 Battery (Android): fix uninitialized variables
Fix #760 and #838
2024-05-02 19:29:13 +08:00
李通洲 023e767237 Shell (Windows): ignore hyfetch 2024-05-02 16:27:13 +08:00
李通洲 688d9b00ab Shell (Linux): don't detect hyfetch as shell 2024-05-02 15:19:43 +08:00
李通洲 c2fe2f70dc DisplayServer (Linux): silence compiler warnings 2024-05-02 15:19:43 +08:00
李通洲 3430c10ec2 Doc: clarify --disk-folders overrides other disk options 2024-05-02 14:09:56 +08:00
李通洲 9afcc00201 Disk (Windows): don't rely on env vars 2024-05-01 19:32:15 +08:00
李通洲 cd783d1267 Presets: add a new example 2024-05-01 16:00:31 +08:00
李通洲 81480532e2 Custom: make --custom-format optional 2024-05-01 15:54:30 +08:00
李通洲 982e8a0117 Disk (Windows): make / an alias of C:\ for --disk-folders 2024-05-01 15:52:38 +08:00
李通洲 8af88a3376 Doc: fix incorrect man page
Fix #828
2024-05-01 11:55:26 +08:00
Val V 9ed2f13c78 Packages (Linux): Extended Source Mage support (#825)
* Extended Source Mage support

* Fix packages format args num

* Correct spelling
2024-05-01 11:25:04 +08:00
李通洲 d7ea774d71 CI: fix release script 2024-04-30 21:42:31 +08:00
Carter Li a4b9784c48 Merge pull request #823 from fastfetch-cli/dev
Release v2.11.0
2024-04-30 20:40:40 +08:00
Carter Li 3fe2d8091a Release: v2.11.0 2024-04-30 19:43:26 +08:00
Carter Li 78c903c403 Camera (macOS): fix building on old xcode 2024-04-30 19:22:45 +08:00
Carter Li c42711ee26 Camera (macOS): try silence system deprecation warnings 2024-04-30 18:56:45 +08:00
李通洲 367264e549 Disk: only detect folders that specified by --disk-folders
Can be used to improve performance by ignoring network disks
2024-04-30 15:42:44 +08:00
李通洲 36a0c273f9 Processing: suggest increasing --processing-timeout when child process timeouts 2024-04-30 14:52:47 +08:00
李通洲 418106c485 Revert "Disk: init variables"
This reverts commit 0576d4ca26.
2024-04-30 14:46:54 +08:00
李通洲 1058e876a7 Revert "Disk (Windows): add --disk-ignore-remote"
This reverts commit c71b04ba93.
2024-04-30 14:46:26 +08:00
李通洲 8721cc1ab5 CPU (Windows): silence compiler warnings 2024-04-30 14:43:12 +08:00
李通洲 e12642e0b9 Fastfetch: make config in jsonc overridable
Fix #821
2024-04-30 09:16:59 +08:00
李通洲 315bbb3020 GPU (Linux): constantly use *_vis_* 2024-04-30 09:16:59 +08:00
李通洲 0576d4ca26 Disk: init variables 2024-04-29 23:33:18 +08:00
李通洲 c309dbb844 Doc: update bug report template 2024-04-29 23:30:55 +08:00
李通洲 c71b04ba93 Disk (Windows): add --disk-ignore-remote 2024-04-29 23:28:20 +08:00
Carter Li f3417b1b05 Merge pull request #818 from fastfetch-cli/dev
Release: v2.10.3
2024-04-29 22:49:37 +08:00
李通洲 c597b7ec3a Release: v2.10.3 2024-04-29 21:47:39 +08:00
李通洲 8b4586b914 Packages: update help messages 2024-04-29 21:47:39 +08:00
李通洲 b65a0e2543 GPU (Linux): fix copy & paste error 2024-04-29 20:43:19 +08:00
李通洲 6e15a44168 GPU (Linux): ignore . when enumerating directories 2024-04-29 20:28:50 +08:00
李通洲 6bd3d2c434 GPU (Linux): greatly improve detection for AMD cards
Completely untested
2024-04-29 20:05:50 +08:00
李通洲 29644ef904 GPU (Linux): disable vmem detection
Ref #816
2024-04-29 13:27:57 +08:00
李通洲 39dfcb6f10 Packages (Linux): optimise nix detection code 2024-04-29 10:04:20 +08:00
Juan Llamas 882b17834c Packages (nix): use hash to cache count and process count manually (#817) 2024-04-29 09:59:05 +08:00
李通洲 bdd2908e6a Doc: update changelog 2024-04-28 10:46:08 +08:00
李通洲 d4a402f4dd Common: slience compiler warnings 2024-04-28 10:34:28 +08:00
李通洲 115b293ff5 CPU (Windows): fix silly bug... 2024-04-27 23:27:16 +08:00
李通洲 6831c095ec TerminalShell (Linux): actually fix #814 2024-04-27 23:12:45 +08:00
李通洲 81fb146869 CPU (Windows): detect max CPU freq with CPUID instruction
Note this only works when Hyper-V is not enabled

Ultimately fixes #800 #812 #815
2024-04-27 23:07:12 +08:00
李通洲 35b54fd064 Separator: add fast path for ascii strings 2024-04-27 17:30:42 +08:00
李通洲 866e65749e Init: tweaks 2024-04-27 16:36:33 +08:00
李通洲 e157b9a51f TerminalShell (Linux): fix nixos wrapped process name
Fix #814
2024-04-27 16:31:39 +08:00
李通洲 74c89cc03f Wifi (Linux): try fixing #811 2024-04-26 19:26:58 +08:00
李通洲 229c6674a4 CMake: fix #810 2024-04-25 15:48:39 +08:00
李通洲 ab8ad7ffc0 Fastfetch: default hideCursor to false
It doesn't make much difference but make user's terminal unusable if fastfetch is not exited correctly
2024-04-25 14:18:25 +08:00
Carter Li 6805cb16fb Packages: support printing total number of nix / flatpak / brew packages
Ref: https://github.com/fastfetch-cli/fastfetch/issues/436#issuecomment-2075469683
2024-04-25 09:16:12 +08:00
Carter Li e596d76430 Display (Linux): don't use *-unknown as name 2024-04-25 09:08:21 +08:00
李通洲 de4afb6507 CI: test with no dependencies installed 2024-04-24 19:40:31 +08:00
李通洲 beb5f479d9 CI: build Linux binaries with Ubuntu 20.04 again...
Ref: #808
2024-04-24 19:03:44 +08:00
李通洲 e660e61027 Swap (Windows): fix x86-32 (v2) 2024-04-24 11:04:03 +08:00
halperyon e3cdecdb14 bedrock version (#809) 2024-04-24 07:45:45 +08:00
李通洲 40320e5efa Swap (Windows): fix detection in i686 build 2024-04-23 23:29:26 +08:00
李通洲 c2fd057126 CI (macOS): revert back to macos 12 before we know what was happening 2024-04-23 22:51:22 +08:00
李通洲 ea1ef0f347 JsonSchema: add missing modules 2024-04-23 22:51:22 +08:00
Guiorgy 04456d9807 allow generation of either deb or rpm package only (#807) 2024-04-23 19:05:55 +08:00
李通洲 18240524dc DisplayServer (Linux): basic support for ukui 2024-04-23 15:32:49 +08:00
Carter Li 42b7d567a1 Merge pull request #806 from fastfetch-cli/dev
Release: v2.10.2
2024-04-23 13:46:23 +08:00
李通洲 2790493cba Release: v2.10.2 2024-04-23 13:43:16 +08:00
李通洲 8eabc49e12 DisplayServer (Linux): fix silly bug that detect x11 as wayland
Fix #805
2024-04-23 13:39:49 +08:00
85 changed files with 1257 additions and 612 deletions
+4
View File
@@ -59,6 +59,10 @@ strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
If you cannot do the instructions above, please upload the core dump file:
## If fastfetch is slow
Use `time fastfetch --stat` to show time usage for each module.
## If my image logo didn't show / work
<!-- Please make sure the terminal does support the image protocol you used. Note Gnome terminal doesn't support any image protocols -->
+1 -1
View File
@@ -11,7 +11,7 @@ Tip: A logo can be displayed by fastfetch without getting into fastfetch's offic
# OS
```
Paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
Paste content of /etc/os-release and /etc/lsb-release here. If none of these files exist, describe a way to identify the distro
```
# Ascii
+51 -36
View File
@@ -14,14 +14,16 @@ jobs:
- name: Install codespell
shell: bash
run: sudo apt update && sudo apt install -y codespell
run: |
sudo apt-get update || true
sudo apt-get install -y codespell
- name: Run Spellchecker
run: codespell
Linux-old-amd64:
name: Linux-old-amd64
runs-on: ubuntu-20.04
no-features-test:
name: No-features-test
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
@@ -32,28 +34,12 @@ jobs:
- name: uname -a
run: uname -a
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: c
- name: configure project
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_LIBNM=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
- name: build project
run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v3
- name: list features
run: ./fastfetch --list-features
@@ -72,15 +58,9 @@ jobs:
- name: run tests
run: ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-old-amd64
path: ./fastfetch-*.*
linux-amd64:
name: Linux-amd64
runs-on: ubuntu-22.04 # Ubuntu 22.04 uses Glibc 2.35. Should be fine with Debian 12, which uses Glibc 2.36 (https://packages.debian.org/source/bookworm/glibc)
runs-on: ubuntu-20.04
permissions:
security-events: write
contents: read
@@ -94,12 +74,12 @@ jobs:
run: uname -a
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
@@ -178,6 +158,45 @@ jobs:
name: fastfetch-linux-aarch64
path: ./fastfetch-*.*
linux-armv7:
name: Linux-armv7
runs-on: ubuntu-22.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: run VM
uses: uraimo/run-on-arch-action@v2
id: runcmd
with:
arch: armv7
distro: ubuntu20.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y wget
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
dpkg -i *.deb
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-armv7
path: ./fastfetch-*.*
musl-amd64:
name: Musl-amd64
runs-on: ubuntu-latest
@@ -258,7 +277,7 @@ jobs:
macos-universal:
name: macOS-universal
runs-on: macos-latest
runs-on: macos-12
permissions:
security-events: write
contents: read
@@ -521,6 +540,7 @@ jobs:
needs:
- linux-amd64
- linux-aarch64
- linux-armv7
- musl-amd64
- musl-aarch64
- macos-universal
@@ -541,11 +561,6 @@ jobs:
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: actions/download-artifact@v4
- name: rm old artifacts
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
run: |
rm -rf fastfetch-*-old-*
- name: create release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
+122 -1
View File
@@ -1,7 +1,128 @@
# 2.11.5
Bugfix:
* Fix logo printing for OpenMandriva (#896)
* Remove `--os-file` in help messages
# 2.11.4
Changes:
* Fastfetch will print a colorless ascii logo in `--pipe` mode for better `lolcat` compatibility. `fastfetch | lolcat` should work and no `--pipe false` needed.
* Previously the logo would be disabled in `--pipe` mode.
* `--os-file` was removed and CMake option `-DCUSTOM_OS_RELEASE_PATH=/path/to/os-release` was added. This option should not used in most cases.
Bugfixes:
* Fix possible out-of-bound memory access (#868)
* Fix Apple Terminal detection (macOS, Terminal)
* Fix doubled output in custom formation (#852)
* Fix deprecation warning for macOS 14.0 hopefully (#860, macOS, Camera)
* Fix memory leaks when passing informative options
* Fix JSON config `size.ndigits` doesn't work
Features:
* Enable `--pipe` mode if environment variable `$NO_COLOR` is set
* Support Armbian and Proxmox distro detection (OS, Linux)
Logo:
* Add Armbian
# 2.11.3
Hotfix for nix (https://github.com/NixOS/nixpkgs/issues/308849#issuecomment-2093962376)
Features:
* Add cmake option `CUSTOM_AMDGPU_IDS_PATH` for specifying custom path of `amdgpu.ids`
Bugfixes:
* Fix hanging when detecting disconnected network drive (Disk, Windows)
* Ensure line ending is printed when printing image logo errors (Logo)
* Revert image logo limitation change in 2.11.2; allow image logo in SSH session and tmux again (#861, Logo)
* Fix doubled output in custom formation (PhysicalDisk, Windows)
# 2.11.2
Hotfix for Debian 11
Changes:
* Error messages when trying to print image logo will only be printed with `--show-errors`
* When generating JSON output, fastfetch will generate an empty array when no result is detected, instead of an error.
Bugfixes:
* Fix segfault in Debian 11 and some old kernels. Regression introduced in 2.11.0 (#845, GPU, Linux)
* Don't try detecting version of raw `sh` shell (#849, Shell, Linux)
* Trim `\r` on Windows
Features:
* Check xdg state home for nix user packages (#837, Packages, Linux)
* Disable image logos in ssh and tmux sessions (#839)
* Support MX Linux distro detection (#847, OS, Linux)
Logo:
* Add KernelOS
* Fix name of DraugerOS
* Add missing `FF_LOGO_LINE_TYPE_SMALL_BIT` flags
* Add MX2
# 2.11.1
Hotfix for Android
Bugfixes:
* Fix uninitialized variables which can cause crashes (#760 #838, Battery, Android)
* Don't detect hyfetch as shell when used as backend of [hyfetch](https://github.com/hykilpikonna/hyfetch)
* Fix incorrect information in man page (#828)
Features:
* Support sorcery package manager detection (Packages, Linux)
* Make `--custom-format` optional (Custom)
* Make `/` an alias of `C:\` for `--disk-folders` (Disk, Windows)
* Build for Linux armv7
Logo:
* Fix colors of Source Mage logo
# 2.11.0
Changes:
* Default `hideCursor` to false. It doesn't make much difference but makes user's terminal unusable if fastfetch is not exited correctly.
* Linux amd64 binaries are built with Ubuntu 20.04 again (#808)
Bugfixes:
* Fix swap usage detection in x86-32 build (Windows, Swap)
* Fix minimum cmake version support (#810)
* Fix wifi detection on platforms that don't use NetworkManager (#811, Wifi, Linux)
* Fix NixOS wrapped process name (#814, Terminal, Linux)
* Fix GPU type detection for AMD cards (#816, GPU, Linux)
* Silence system deprecation warnings (#822, Camera, macOS)
Features:
* Add basic support DE detection support for UKUI (DE, Linux)
* Support printing total number of nix / flatpak / brew packages (Packages)
* See `fastfetch -h packages-format` for detail
* Better max CPU frequency detection support with `CPUID / 16H` instruction (CPU, Windows)
* This requires Intel Core I Gen 6 or newer, and with `Virtual Machine Platform` Windows feature disabled. X86 only.
* Improve performance of nix packages detection (Packages, Linux)
* Make config specified in JSONC overridable by command line flags
* Note this change only make global config overridable; module configs are still not
* Suggest increasing `--processing-timeout` when child process timeouts
* Only detect folders that specified by `--disk-folders`
* Previously `--disk-folders` only omits unmatched disks from output
* This option can be used to improve detection performance by ignoring slow network drives
# 2.10.2
Bugfixes:
* Fix a regression that detect x11 as wayland (#805, WM, Linux)
# 2.10.1
Bugfixes:
* fix build with `-DENABLE_DBUS=OFF`
* Fix build with `-DENABLE_DBUS=OFF` (Linux)
# 2.10.0
+31 -13
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.10.1
VERSION 2.11.5
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -79,6 +79,8 @@ option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
if (LINUX)
set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
set(CUSTOM_AMDGPU_IDS_PATH "" CACHE STRING "Custom path to file amdgpu.ids, defaults to `/usr/share/libdrm/amdgpu.ids`")
set(CUSTOM_OS_RELEASE_PATH "" CACHE STRING "Custom path to file os-release, defaults to `/etc/os-release`")
endif()
####################
@@ -255,7 +257,7 @@ file(GLOB LOGO_FILES "src/logo/ascii/*.txt")
set(LOGO_BUILTIN_H "#pragma once\n#pragma GCC diagnostic ignored \"-Wtrigraphs\"\n\n")
foreach(file ${LOGO_FILES})
fastfetch_load_text("${file}" content)
get_filename_component(file "${file}" NAME_WLE)
get_filename_component(file "${file}" NAME_WE)
string(TOUPPER "${file}" file)
string(REGEX REPLACE "\\$\\{c([0-9]+)\\}" "$\\1" content "${content}")
set(LOGO_BUILTIN_H "${LOGO_BUILTIN_H}#define FASTFETCH_DATATEXT_LOGO_${file} ${content}\n")
@@ -784,6 +786,14 @@ if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
endif()
if(NOT "${CUSTOM_AMDGPU_IDS_PATH}" STREQUAL "")
message(STATUS "Custom file path of amdgpu.ids: ${CUSTOM_AMDGPU_IDS_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
endif()
if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "")
message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
endif()
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
if(NOT ENABLE_${VARNAME})
@@ -933,10 +943,6 @@ if(ENABLE_THREADS)
endif()
endif()
if(ENABLE_PCI_MEMORY)
target_compile_definitions(libfastfetch PRIVATE FF_USE_PCI_MEMORY)
endif()
if(LINUX)
target_link_libraries(libfastfetch
PRIVATE "m"
@@ -1147,16 +1153,28 @@ endif()
if(LINUX)
find_program(HAVE_DPKG "dpkg")
find_program(HAVE_RPMBUILD "rpmbuild")
if(HAVE_DPKG AND HAVE_RPMBUILD)
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
if(HAVE_DPKG)
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB")
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
if(NOT IS_MUSL)
EXECUTE_PROCESS (
COMMAND getconf GNU_LIBC_VERSION
OUTPUT_VARIABLE GLIBC_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
STRING (REPLACE "glibc " "" GLIBC_VERSION ${GLIBC_VERSION})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= ${GLIBC_VERSION})")
endif()
endif()
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
find_program(HAVE_RPMBUILD "rpmbuild")
if(HAVE_RPMBUILD)
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
endif()
endif()
set(CPACK_SET_DESTDIR ON)
-34
View File
@@ -1,34 +0,0 @@
# Development help
This file is not an official documentation!
Here i just add things that are easy to forget.
## Features i am planning to implement
### Specific
- [ ] Split the project in different libs / executables, all linking static by default:
- `libffdetect`: contains all the detection stuff. To be used by anything that needs system information
- `libffprint`: contains the printing functions, logos, format etc
- `fastfetch` and `flashfetch`: Executables, that initialize the config of libffprint. Fist one at runtime, second one at compile time
- [ ] Make LocalIP module more configurable
- [ ] Automatic migrate old config files to newer versions
- [ ] ZSH completions
- [ ] Fish completions
- [ ] Make CPU usage detection much faster and more accurate
- [ ] Detect CPU usage in a common detection method and expose it both to the cpuUsage module and the cpu format string
- [ ] Per session caching
### General
- More presets
- More logos
- More package managers
- More DE detections
- More WM theme detections
- More terminal font detections
- Performance optimizations
- More module specific options
- Better error handling, especially the messages shown when using --show-errors
- Using package managers libraries for package count detection instead own. E.g. using libalpm instead of counting files in /var/lib/pacman/local
- Better documentation (especially default config file and the various --help options. Colored output?)
- General feature parity with neofetch, to demonstrate supremity of c
+2 -2
View File
@@ -29,8 +29,8 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
Some distros packaged an outdated fastfetch version. Older version is not supported, please always ensure that the latest version is used.
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or above)
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch-<version>-Linux.deb` (for Ubuntu 22.04 or above and Debian 12 or above).
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
* Arch Linux: `sudo pacman -S fastfetch`
* Fedora: `sudo dnf install fastfetch`
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
-1
View File
@@ -360,7 +360,6 @@ __fastfetch_completion()
local FF_OPTIONS_PATH=(
"-c"
"--config"
"--os-file"
"--lib-pci"
"--lib-vulkan"
"--lib-wayland"
+5 -8
View File
@@ -107,12 +107,12 @@ To list all available modules, use \fB \-\-list\-modules \fR
.SS "Config Files"
fastfetch supports two types of config files. The legacy
configuration files and a JSONC based format.
Fastfetch uses JSONC based format for configuration. Fastfetch doesn't generate
config file automatically; it should be generated manually by \fB \-\-gen\-config\fR.
The config file will be saved in \fB~/.config/fastfetch/config.jsonc\fR by default.
A JSONC config file is a JSON file that also supports comments with (//). Those
files must have the extension '.jsonc'. You can migrate a legacy config
file to the JSONC format by using \fB\-\-gen\-config\fR.
files must have the extension '.jsonc'.
The specified configuration/preset files are searched in the following order:
@@ -122,10 +122,7 @@ The specified configuration/preset files are searched in the following order:
3. relative to /usr/share/fastfetch/presets/
When both a '.jsonc' and a '.conf' file with the same name is found,
the '.jsonc' file is preferred.
Fastfetch provides some default presets. List them with \fB \-\-print\-available\-presets\fR.
Fastfetch provides some default presets. List them with \fB\-\-list\-presets\fR.
.SH "SEE ALSO"
.BR neofetch (1)
+10 -9
View File
@@ -294,10 +294,6 @@
"type": "string",
"description": "The name of the player to use for module Media and Player. Linux only"
},
"osFile": {
"type": "string",
"description": "Set the path to the file containing OS information. Linux only"
},
"dsForceDrm": {
"description": "Force display detection to use DRM. Linux only",
"oneOf": [
@@ -679,6 +675,7 @@
"board",
"break",
"brightness",
"camera",
"chassis",
"cpu",
"cpuusage",
@@ -772,6 +769,10 @@
"const": "board",
"description": "Print mather board name and other info"
},
{
"const": "camera",
"description": "Print available cameras"
},
{
"const": "cursor",
"description": "Print cursor style name"
@@ -1112,6 +1113,9 @@
"maxItems": 2
}
}
},
"key": {
"$ref": "#/$defs/key"
}
}
},
@@ -1169,10 +1173,7 @@
"description": "Text to print",
"type": "string"
}
},
"required": [
"format"
]
}
},
{
"title": "Display",
@@ -1233,7 +1234,7 @@
},
"folders": {
"type": "string",
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points"
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options"
},
"showExternal": {
"type": "boolean",
+1 -1
View File
@@ -1,5 +1,5 @@
{
"$schema": "file:///C:/msys64/home/zhang/fastfetch/doc/json_schema.json",
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "small"
},
+85
View File
@@ -0,0 +1,85 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "small",
"padding": {
"top": 1
}
},
"display": {
"separator": "",
"keyWidth": 15
},
"modules": [
{
"key": "╭───────────╮",
"type": "custom"
},
{
// draw borders first to make colors of left and right border consistant
"key": "│ │\u001b[11D\u001b[31m user",
"type": "title",
"format": "{1}"
},
{
"key": "│ │\u001b[11D\u001b[32m󰇅 hname",
"type": "title",
"format": "{2}"
},
{
"key": "│ │\u001b[11D\u001b[33m󰅐 uptime",
"type": "uptime"
},
{
"key": "│ │\u001b[11D\u001b[34m󰟾 distro",
"type": "os"
},
{
"key": "│ │\u001b[11D\u001b[35m kernel",
"type": "kernel"
},
{
"key": "│ │\u001b[11D\u001b[36m󰇄 desktop",
"type": "de"
},
{
"key": "│ │\u001b[11D\u001b[31m term",
"type": "terminal"
},
{
"key": "│ │\u001b[11D\u001b[32m shell",
"type": "shell"
},
{
"key": "│ │\u001b[11D\u001b[33m󰍛 cpu",
"type": "cpu"
},
{
"key": "│ │\u001b[11D\u001b[34m󰉉 disk",
"type": "disk",
"folders": "/"
},
{
"key": "│ │\u001b[11D\u001b[35m memory",
"type": "memory"
},
{
"key": "│ │\u001b[11D\u001b[36m󰩟 network",
"type": "localip",
"format": "{1} ({4})"
},
{
"key": "├───────────┤",
"type": "custom"
},
{
"key": "│ │\u001b[11D\u001b[m colors",
"type": "colors",
"symbol": "circle"
},
{
"key": "╰───────────╯",
"type": "custom"
}
]
}
+1 -2
View File
@@ -9,8 +9,7 @@
"modules": [
{
"type": "theme",
"key": "T",
"format": "{7}"
"key": "T"
},
{
"type": "icons",
+9 -12
View File
@@ -1,16 +1,16 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"display": {
"size": {
"maxPrefix": "MB",
"ndigits": 0
}
},
"modules": [
"title",
"separator",
{
"type": "os",
"format": "{3} {12}"
},
{
"type": "host",
"format": "{/2}{-}{/}{2}{?3} {3}{?}"
},
"os",
"host",
"kernel",
"uptime",
"packages",
@@ -23,10 +23,7 @@
"de",
"wm",
"wmtheme",
{
"type": "theme",
"format": "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}"
},
"theme",
"icons",
"terminal",
{
+2 -2
View File
@@ -11,7 +11,7 @@
bool ffParseModuleOptions(const char* key, const char* value)
{
if (!ffStrStartsWith(key, "--") || !isalpha(key[2])) return false;
if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false;
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules)
{
@@ -102,7 +102,7 @@ static void parseStructureCommand(
}
}
if(isalpha(line[0]))
if(ffCharIsEnglishAlphabet(line[0]))
{
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
{
+5 -5
View File
@@ -238,9 +238,6 @@ void ffListFeatures(void)
#ifdef FF_HAVE_DDCUTIL
"libddcutil\n"
#endif
#if __has_include(<linux/videodev2.h>)
"videodev2\n"
#endif
#ifdef FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
@@ -250,8 +247,11 @@ void ffListFeatures(void)
#ifdef FF_USE_SYSTEM_YYJSON
"System yyjson\n"
#endif
#ifdef FF_USE_PCI_MEMORY
"PCI memory\n"
#if __has_include(<linux/videodev2.h>)
"linux/videodev2\n"
#endif
#if __has_include(<linux/wireless.h>)
"linux/wireless\n"
#endif
""
, stdout);
+1 -1
View File
@@ -94,7 +94,7 @@ static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_mut_doc* jsonDoc)
{
if(!isalpha(type[0])) return false;
if(!ffCharIsEnglishAlphabet(type[0])) return false;
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules)
{
+1 -1
View File
@@ -4,7 +4,7 @@
#include <stdarg.h>
//Clang doesn't define __SANITIZE_ADDRESS__ but defines __has_feature(address_sanitizer)
#if defined(__has_feature)
#if !defined(__SANITIZE_ADDRESS__) && defined(__has_feature)
#if __has_feature(address_sanitizer)
#define __SANITIZE_ADDRESS__
#endif
+2 -8
View File
@@ -8,10 +8,7 @@ static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const ar
{
const char* error = ffProcessAppendOutput(buffer, argv, false);
if (!error)
{
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
}
ffStrbufTrimRightSpace(buffer);
return error;
}
@@ -19,9 +16,6 @@ static inline const char* ffProcessAppendStdErr(FFstrbuf* buffer, char* const ar
{
const char* error = ffProcessAppendOutput(buffer, argv, true);
if (!error)
{
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
}
ffStrbufTrimRightSpace(buffer);
return error;
}
+1 -1
View File
@@ -68,7 +68,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) timeout";
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
}
else if (pollfd.revents & POLLERR)
{
+1 -1
View File
@@ -96,7 +96,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
{
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "WaitForSingleObject(hChildPipeRead) failed or timeout";
return "WaitForSingleObject(hChildPipeRead) failed or timeout (try increasing --processing-timeout)";
}
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
+25 -29
View File
@@ -1,5 +1,7 @@
#include "fastfetch.h"
#include "common/properties.h"
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#ifdef _WIN32
@@ -95,50 +97,44 @@ bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
{
FILE* file = fopen(filename, "r");
if(file == NULL)
FF_AUTO_CLOSE_FILE FILE* file = fopen(filename, "r");
if (file == NULL)
return false;
bool valueStorage[4];
bool* unsetValues;
bool valueStorage[32];
bool* unsetValues = valueStorage;
if(numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
if (numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
unsetValues = malloc(sizeof(bool) * numQueries);
else
unsetValues = valueStorage;
bool allSet = true;
for(uint32_t i = 0; i < numQueries; i++)
for (uint32_t i = 0; i < numQueries; i++)
{
if((unsetValues[i] = queries[i].buffer->length == 0))
unsetValues[i] = queries[i].buffer->length == 0;
if (unsetValues[i])
allSet = false;
}
if(allSet)
goto done;
char* line = NULL;
size_t len = 0;
while (getline(&line, &len, file) != -1)
if (!allSet)
{
for(uint32_t i = 0; i < numQueries; i++)
{
if(!unsetValues[i])
continue;
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
uint32_t currentLength = queries[i].buffer->length;
queries[i].buffer->length = 0;
if(!ffParsePropLine(line, queries[i].start, queries[i].buffer))
queries[i].buffer->length = currentLength;
while (getline(&line, &len, file) != -1)
{
for(uint32_t i = 0; i < numQueries; i++)
{
if(!unsetValues[i])
continue;
uint32_t currentLength = queries[i].buffer->length;
queries[i].buffer->length = 0;
if(!ffParsePropLine(line, queries[i].start, queries[i].buffer))
queries[i].buffer->length = currentLength;
}
}
}
if(line != NULL)
free(line);
done:
fclose(file);
if(unsetValues != valueStorage)
free(unsetValues);
return true;
+2 -9
View File
@@ -937,17 +937,10 @@
"default": "-"
}
},
{
"long": "os-file",
"desc": "Set the additional file path which containing OS information",
"remark": "Linux only",
"arg": {
"type": "path"
}
},
{
"long": "disk-folders",
"desc": "A colon (semicolon on Windows) separated list of folder paths for the disk output",
"desc": "A colon (semicolon on Windows) separated list of folder paths to be detected",
"remark": "On Windows, a drive latter must be upper cased and end with \"\\\". \"/\" is used as an alias of the system drive. This option overrides other disk-show-* options",
"arg": {
"type": "path",
"default": "Auto detection using mount-points"
+4 -3
View File
@@ -3,7 +3,8 @@ Usage: fastfetch --color <color>
<color> must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m".
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
Examples:
--color 35: sets the color to magenta. `--color magenta` is also supported
--color 4;92: sets the color to bright Green with underline
--color 5;104: blinking text on a blue background
--color 35: sets the color to magenta. `--color magenta` is also supported
--color 38;5;38: sets the color to 38th color of ANSI 256 colors
--color 4;92: sets the color to bright Green with underline
--color 5;104: blinking text on a blue background
If no color is set, the main color of the logo will be used.
+3
View File
@@ -40,6 +40,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
@@ -77,6 +78,8 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
ffStrbufAppendS(&battery->status, "AC powered");
-3
View File
@@ -170,8 +170,5 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
if(results->length == 0)
return "\"/sys/class/power_supply/\" doesn't contain any battery folder";
return NULL;
}
+3 -6
View File
@@ -1,4 +1,6 @@
#include "battery.h"
#include "common/io/io.h"
#include "util/windows/unicode.h"
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
@@ -20,11 +22,6 @@ NtPowerInformation(
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength);
static inline void wrapCloseHandle(HANDLE* handle)
{
if(*handle)
CloseHandle(*handle);
}
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
{
if(*hdev)
@@ -52,7 +49,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
continue;
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
HANDLE FF_AUTO_CLOSE_FD hBattery =
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hBattery == INVALID_HANDLE_VALUE)
+22 -1
View File
@@ -1,10 +1,31 @@
#include "camera.h"
#include "common/io/io.h"
#import <AVFoundation/AVCaptureDevice.h>
// warning: 'AVCaptureDeviceTypeExternalUnknown' is deprecated
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
const char* ffDetectCamera(FFlist* result)
{
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
FF_SUPPRESS_IO(); // #822
AVCaptureDeviceType deviceType;
#ifdef MAC_OS_VERSION_14_0
if (@available(macOS 14.0, *))
{
deviceType = AVCaptureDeviceTypeExternal;
}
else
#endif
{
deviceType = AVCaptureDeviceTypeExternalUnknown;
}
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera, deviceType]
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
if (!session)
return "Failed to create AVCaptureDeviceDiscoverySession";
+28 -1
View File
@@ -50,6 +50,31 @@ typedef struct FFSmbiosProcessorInfo
uint16_t ThreadEnabled; // varies
} FFSmbiosProcessorInfo;
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
{
uint32_t base = 0, max = 0, bus = 0, unused = 0;
if (!__get_cpuid(0x16, &base, &max, &bus, &unused))
return "Unsupported instruction";
// cpuid returns 0 MHz when hyper-v is enabled
if (base) cpu->frequencyBase = base / 1000.0;
if (max) cpu->frequencyMax = max / 1000.0;
return NULL;
}
#else
inline static const char* detectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
{
return "Unsupported platform";
}
#endif
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
{
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO];
@@ -114,6 +139,7 @@ static const char* detectByRegistry(FFCPUResult* cpu)
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
if (detectSpeedByCpuid(cpu) != NULL || cpu->frequencyBase != cpu->frequencyBase)
{
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
@@ -141,7 +167,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (error)
return error;
detectMaxSpeedBySmbios(cpu);
if (cpu->frequencyMax != cpu->frequencyMax)
detectMaxSpeedBySmbios(cpu);
if(options->temp)
ffDetectSmbiosTemp(&cpu->temperature, NULL);
+25 -2
View File
@@ -1,6 +1,29 @@
#include "disk.h"
const char* ffDetectDisksImpl(FFlist* disks);
bool ffDiskMatchMountpoint(FFDiskOptions* options, const char* mountpoint)
{
#ifdef _WIN32
const char separator = ';';
#else
const char separator = ':';
#endif
uint32_t mountpointLength = (uint32_t) strlen(mountpoint);
uint32_t startIndex = 0;
while(startIndex < options->folders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&options->folders, startIndex, separator);
uint32_t folderLength = colonIndex - startIndex;
if (folderLength == mountpointLength && memcmp(options->folders.chars + startIndex, mountpoint, mountpointLength) == 0)
return true;
startIndex = colonIndex + 1;
}
return false;
}
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
{
@@ -9,7 +32,7 @@ static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
{
const char* error = ffDetectDisksImpl(disks);
const char* error = ffDetectDisksImpl(options, disks);
if (error) return error;
if (disks->length == 0) return "No disks found";
+3
View File
@@ -26,3 +26,6 @@ typedef struct FFDisk
* If error is not set, disks contains at least one disk.
*/
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks /* list of FFDisk */);
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks);
bool ffDiskMatchMountpoint(FFDiskOptions* options, const char* mountpoint);
+7 -2
View File
@@ -90,7 +90,7 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk)
}
#endif
const char* ffDetectDisksImpl(FFlist* disks)
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
int size = getfsstat(NULL, 0, MNT_WAIT);
@@ -103,7 +103,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
for(struct statfs* fs = buf; fs < buf + size; ++fs)
{
if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
if(__builtin_expect(options->folders.length, 0))
{
if(!ffDiskMatchMountpoint(options, fs->f_mntonname))
continue;
}
else if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
continue;
#ifdef __FreeBSD__
+7 -2
View File
@@ -250,7 +250,7 @@ static void detectStats(FFDisk* disk)
#endif
}
const char* ffDetectDisksImpl(FFlist* disks)
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
FILE* mountsFile = setmntent("/proc/mounts", "r");
if(mountsFile == NULL)
@@ -260,7 +260,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
while((device = getmntent(mountsFile)))
{
if(!isPhysicalDevice(device))
if (__builtin_expect(options->folders.length, 0))
{
if (!ffDiskMatchMountpoint(options, device->mnt_dir))
continue;
}
else if(!isPhysicalDevice(device))
continue;
//We have a valid device, add it to the list
+71 -41
View File
@@ -1,53 +1,102 @@
#include "disk.h"
#include "common/io/io.h"
#include "common/thread.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <winioctl.h>
#include <assert.h>
const char* ffDetectDisksImpl(FFlist* disks)
static unsigned __stdcall testRemoteVolumeAccessable(void* mountpoint)
{
FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(
(wchar_t*) mountpoint,
READ_CONTROL,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
return 0;
}
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
wchar_t buf[MAX_PATH + 1];
uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf);
if (length == 0 || length >= sizeof(buf) / sizeof(*buf))
return "GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf) failed";
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
// For cross-platform portability; used by `presets/examples/13.jsonc`
if (__builtin_expect(options->folders.length == 1 && options->folders.chars[0] == '/', 0))
{
wchar_t path[MAX_PATH + 1];
GetSystemWindowsDirectoryW(path, sizeof(path) / sizeof(*path));
ffStrbufSetF(&options->folders, "%c:\\", (char) path[0]);
}
for(uint32_t i = 0; i < length; i++)
{
wchar_t* mountpoint = buf + i;
ffStrbufSetWS(&buffer, mountpoint);
i += buffer.length;
UINT driveType = GetDriveTypeW(mountpoint);
if(driveType == DRIVE_NO_ROOT_DIR)
if (__builtin_expect((long) options->folders.length, 0))
{
i += (uint32_t)wcslen(mountpoint);
continue;
if (!ffDiskMatchMountpoint(options, buffer.chars))
continue;
}
else if(driveType == DRIVE_NO_ROOT_DIR)
continue;
FFDisk* disk = ffListAdd(disks);
if(!GetDiskFreeSpaceExW(
disk->filesUsed = 0;
disk->filesTotal = 0;
disk->bytesTotal = 0;
disk->bytesFree = 0;
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->bytesAvailable = 0;
disk->createTime = 0;
ffStrbufInit(&disk->filesystem);
ffStrbufInit(&disk->name);
ffStrbufInitMove(&disk->mountpoint, &buffer);
ffStrbufInit(&disk->mountFrom);
disk->type = driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM
? FF_DISK_VOLUME_TYPE_EXTERNAL_BIT
: driveType == DRIVE_FIXED
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
: FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
{
wchar_t volumeName[MAX_PATH + 1];
mountpoint[2] = L'\0';
if(QueryDosDeviceW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
ffStrbufSetWS(&disk->mountFrom, volumeName);
mountpoint[2] = L'\\';
}
#ifdef FF_HAVE_THREADS
if (driveType == DRIVE_REMOTE)
{
FFThreadType thread = ffThreadCreate(testRemoteVolumeAccessable, mountpoint);
if (!ffThreadJoin(thread, 500))
continue;
}
#endif
GetDiskFreeSpaceExW(
mountpoint,
(PULARGE_INTEGER)&disk->bytesAvailable,
(PULARGE_INTEGER)&disk->bytesTotal,
(PULARGE_INTEGER)&disk->bytesFree
))
{
disk->bytesTotal = 0;
disk->bytesFree = 0;
disk->bytesAvailable = 0;
}
disk->bytesUsed = 0; // To be filled in ./disk.c
);
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else if(driveType == DRIVE_FIXED)
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
else
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
ffStrbufInit(&disk->filesystem);
ffStrbufInit(&disk->name);
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
@@ -74,25 +123,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
WIN32_FILE_ATTRIBUTE_DATA data;
if(GetFileAttributesExW(mountpoint, GetFileExInfoStandard, &data) && data.ftCreationTime.dwHighDateTime > 0)
disk->createTime = (*(uint64_t*) &data.ftCreationTime - 116444736000000000ull) / 10000ull;
else
disk->createTime = 0;
ffStrbufInitWS(&disk->mountpoint, mountpoint);
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
{
wchar_t volumeName[MAX_PATH + 1];
mountpoint[2] = L'\0';
if(QueryDosDeviceW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
ffStrbufInitWS(&disk->mountFrom, volumeName);
else
ffStrbufInit(&disk->mountFrom);
}
//Unsupported
disk->filesUsed = 0;
disk->filesTotal = 0;
i += disk->mountpoint.length;
}
return NULL;
@@ -13,6 +13,7 @@
#define FF_DE_PRETTY_BUDGIE "Budgie"
#define FF_DE_PRETTY_CDE "CDE"
#define FF_DE_PRETTY_UNITY "Unity"
#define FF_DE_PRETTY_UKUI "UKUI"
#define FF_WM_PRETTY_KWIN "KWin"
#define FF_WM_PRETTY_MUTTER "Mutter"
@@ -118,7 +118,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
rotation,
display.edidName.length
? &display.edidName
: display.description.length
: display.description.length && !ffStrbufEndsWithS(&display.description, "-unknown")
? &display.description
: &display.name,
display.type,
@@ -135,7 +135,7 @@ void ffdsConnectWayland(FFDisplayServerResult* result)
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
//If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session.
if(xdgSessionType != NULL && ffStrEqualsIgnCase(xdgSessionType, "wayland"))
if(xdgSessionType != NULL && !ffStrEqualsIgnCase(xdgSessionType, "wayland"))
return;
//If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY or WAYLAND_SOCKET is set.
@@ -6,7 +6,7 @@
static void waylandZwlrTransformListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, int32_t transform)
{
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->transform = transform;
wldata->transform = (enum wl_output_transform) transform;
}
static void waylandZwlrScaleListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, wl_fixed_t scale)
+10 -1
View File
@@ -75,7 +75,9 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name)
ffStrEqualsIgnCase(name, "kwin_wayland_wrapper") ||
ffStrEqualsIgnCase(name, "kwin_x11") ||
ffStrEqualsIgnCase(name, "kwin_x11_wrapper") ||
ffStrEqualsIgnCase(name, "kwin")
ffStrEqualsIgnCase(name, "kwin") ||
ffStrEndsWithIgnCase(name, "-kwin_wayland") ||
ffStrEndsWithIgnCase(name, "-kwin_x11")
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN);
else if(
ffStrEqualsIgnCase(name, "gnome-shell") ||
@@ -231,6 +233,13 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
ffStrbufSetS(&result->deProcessName, "dtsession");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CDE);
}
else if(
ffStrEqualsIgnCase(name, "ukui-session")
) {
ffStrbufSetS(&result->deProcessName, "ukui-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_UKUI);
}
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
+105 -71
View File
@@ -15,23 +15,6 @@
#include <inttypes.h>
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
{
const FFlist* tempsResult = ffDetectTemps();
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
{
// https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#hwmon-interfaces
// FIXME: this code doesn't take multiGPUs into count
// The kernel exposes the device class multiplied by 256 for some reason
if(tempValue->deviceClass == deviceClass * 256)
{
gpu->temperature = tempValue->value;
return;
}
}
}
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
ffStrbufAppendS(pciDir, "/driver");
@@ -56,33 +39,66 @@ static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer
}
}
static void pciDetectVmem(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
// Works for AMD GPUs
// https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#mem-info-vis-vram-total
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
uint64_t size = 0;
if (ffReadFileBuffer(pciDir->chars, buffer) && (size = ffStrbufToUInt(buffer, 0)))
{
gpu->type = size > 1024UL * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
if (gpu->type == FF_GPU_TYPE_DISCRETE)
gpu->dedicated.total = size;
else
gpu->shared.total = size;
const uint32_t pciDirLen = pciDir->length;
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
ffStrbufAppendS(pciDir, "/mem_info_vram_used");
if (ffReadFileBuffer(pciDir->chars, buffer) && (size = ffStrbufToUInt(buffer, 0)))
ffStrbufAppendS(pciDir, "/hwmon/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
if (!dirp) return;
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
break;
}
if (!entry) return;
ffStrbufAppendS(pciDir, entry->d_name);
ffStrbufAppendC(pciDir, '/');
const uint32_t hwmonLen = pciDir->length;
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
if (ffPathExists(pciDir->chars, FF_PATHTYPE_FILE))
gpu->type = FF_GPU_TYPE_INTEGRATED;
else
gpu->type = FF_GPU_TYPE_DISCRETE;
uint64_t value = 0;
if (options->temp)
{
ffStrbufSubstrBefore(pciDir, hwmonLen);
ffStrbufAppendS(pciDir, "temp1_input"); // The on die GPU temperature in millidegrees Celsius
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
gpu->temperature = (double) value / 1000;
}
ffStrbufSubstrBefore(pciDir, hwmonLen);
ffStrbufAppendS(pciDir, "freq1_input"); // The gfx/compute clock in hertz
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
gpu->frequency = (double) value / (1000 * 1000 * 1000);
if (options->driverSpecific)
{
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
gpu->dedicated.used = size;
else
gpu->shared.used = size;
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
gpu->dedicated.used = value;
else
gpu->shared.used = value;
}
}
}
}
static void pciDetectVfreq(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
if (!ffStrbufEndsWithS(pciDir, "/device")) // Must be in `/sys/class/drm/cardN/device`
return;
@@ -98,14 +114,20 @@ static void pciDetectVfreq(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
str[len] = '\0';
gpu->frequency = (double) strtoul(str, NULL, 10) / 1000.0;
}
if (ffStrbufStartsWithS(&gpu->name, "Intel "))
ffStrbufSubstrAfter(&gpu->name, (uint32_t) strlen("Intel "));
gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
static bool loadPciIds(FFstrbuf* pciids)
{
#ifdef FF_CUSTOM_PCI_IDS_PATH
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids);
if (pciids->length > 0) return true;
#endif
#else
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
@@ -116,6 +138,8 @@ static bool loadPciIds(FFstrbuf* pciids)
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
#endif
return false;
}
@@ -168,7 +192,11 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
{
char query[32];
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name);
#else
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
#endif
}
}
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
@@ -182,47 +210,53 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
ffStrbufInit(&pciids);
loadPciIds(&pciids);
}
if (pciids.length)
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
}
pciDetectVmem(gpu, drmDir, buffer);
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
pciDetectVfreq(gpu, drmDir, buffer);
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
pciDetectDriver(gpu, drmDir, buffer);
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
},
}, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
}, "libnvidia-ml.so");
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
pciDetectAmdSpecific(options, gpu, drmDir, buffer);
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
pciDetectIntelSpecific(gpu, drmDir, buffer);
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (options->temp || options->driverSpecific)
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
},
}, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
}, "libnvidia-ml.so");
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
#ifdef __linux__
if(options->temp && gpu->temperature != gpu->temperature)
pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
#endif
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
}
return NULL;
}
@@ -231,7 +265,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F
{
uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t");
if (index == buffer->length) return "display-subsystem?";
index += strlen("apple,agx-t");
index += (uint32_t) strlen("apple,agx-t");
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
gpu->deviceId = strtoul(buffer->chars + index, NULL, 10);
+81 -21
View File
@@ -2,11 +2,15 @@
#include "common/properties.h"
#include "common/parsing.h"
#include "common/io/io.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include <string.h>
#include <stdlib.h>
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
static inline bool allRelevantValuesSet(const FFOSResult* result)
{
return result->id.length > 0
@@ -15,18 +19,25 @@ static inline bool allRelevantValuesSet(const FFOSResult* result)
;
}
static bool parseFile(const char* fileName, FFOSResult* result)
static bool parseLsbRelease(const char* fileName, FFOSResult* result)
{
return ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
{"NAME =", &result->name},
{"DISTRIB_DESCRIPTION =", &result->prettyName},
{"PRETTY_NAME =", &result->prettyName},
return ffParsePropFileValues(fileName, 4, (FFpropquery[]) {
{"DISTRIB_ID =", &result->id},
{"DISTRIB_DESCRIPTION =", &result->prettyName},
{"DISTRIB_RELEASE =", &result->version},
{"DISTRIB_CODENAME =", &result->codename},
});
}
static bool parseOsRelease(const char* fileName, FFOSResult* result)
{
return ffParsePropFileValues(fileName, 10, (FFpropquery[]) {
{"PRETTY_NAME =", &result->prettyName},
{"NAME =", &result->name},
{"ID =", &result->id},
{"ID_LIKE =", &result->idLike},
{"VARIANT =", &result->variant},
{"VARIANT_ID =", &result->variantID},
{"DISTRIB_RELEASE =", &result->version},
{"VERSION =", &result->version},
{"VERSION_ID =", &result->versionID},
{"VERSION_CODENAME =", &result->codename},
@@ -132,15 +143,48 @@ static void getDebianVersion(FFOSResult* result)
ffStrbufSet(&result->versionID, &debianVersion);
}
static bool detectDebianDerived(FFOSResult* result)
{
if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Armbian 24.2.1 bookworm
{
ffStrbufSetS(&result->name, "Armbian");
ffStrbufSetS(&result->id, "armbian");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufClear(&result->versionID);
uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1;
uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' ');
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
return true;
}
else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE))
{
ffStrbufSetS(&result->id, "pve");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufSetS(&result->name, "Proxmox VE");
ffStrbufClear(&result->versionID);
if (ffProcessAppendStdOut(&result->versionID, (char* const[]) {
"/usr/bin/pveversion",
NULL,
}) == NULL) // pve-manager/8.2.2/9355359cd7afbae4 (running kernel: 6.8.4-2-pve)
{
ffStrbufSubstrBeforeLastC(&result->versionID, '/');
ffStrbufSubstrAfterFirstC(&result->versionID, '/');
}
ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars);
return true;
}
return false;
}
static void detectOS(FFOSResult* os)
{
if(instance.config.general.osFile.length > 0)
{
parseFile(instance.config.general.osFile.chars, os);
return;
}
#ifdef FF_CUSTOM_OS_RELEASE_PATH
parseOsRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os);
parseLsbRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os);
return;
#endif
if(instance.config.general.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
if(instance.config.general.escapeBedrock && parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os))
{
if(os->id.length == 0)
ffStrbufAppendS(&os->id, "bedrock");
@@ -151,18 +195,31 @@ static void detectOS(FFOSResult* os)
if(os->prettyName.length == 0)
ffStrbufAppendS(&os->prettyName, "Bedrock Linux");
return;
if(parseOsRelease("/bedrock" FASTFETCH_TARGET_DIR_ETC "/os-release", os) && allRelevantValuesSet(os))
return;
}
parseFile(FASTFETCH_TARGET_DIR_ETC"/os-release", os);
if(allRelevantValuesSet(os))
// Refer: https://gist.github.com/natefoo/814c5bf936922dad97ff
// Hack for MX Linux. See #847
if(parseLsbRelease(FASTFETCH_TARGET_DIR_ETC "/lsb-release", os))
{
if (ffStrbufEqualS(&os->id, "MX"))
{
ffStrbufSetStatic(&os->name, "MX");
ffStrbufSetStatic(&os->idLike, "debian");
return;
}
// For archlinux
if (ffStrbufEqualS(&os->version, "rolling"))
ffStrbufClear(&os->version);
}
if(parseOsRelease(FASTFETCH_TARGET_DIR_ETC "/os-release", os) && allRelevantValuesSet(os))
return;
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", os);
if(allRelevantValuesSet(os))
return;
parseFile(FASTFETCH_TARGET_DIR_ETC"/lsb-release", os);
parseOsRelease(FASTFETCH_TARGET_DIR_USR "/lib/os-release", os);
}
void ffDetectOSImpl(FFOSResult* os)
@@ -172,5 +229,8 @@ void ffDetectOSImpl(FFOSResult* os)
if(ffStrbufIgnCaseEqualS(&os->id, "ubuntu"))
getUbuntuFlavour(os);
else if(ffStrbufIgnCaseEqualS(&os->id, "debian"))
getDebianVersion(os);
{
if (!detectDebianDerived(os))
getDebianVersion(os);
}
}
+1
View File
@@ -26,6 +26,7 @@ typedef struct FFPackagesResult
uint32_t rpm;
uint32_t scoop;
uint32_t snap;
uint32_t sorcery;
uint32_t winget;
uint32_t xbps;
+160 -12
View File
@@ -118,28 +118,146 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons
return sum;
}
static bool isValidNixPkg(FFstrbuf* pkg)
{
if (!ffPathExists(pkg->chars, FF_PATHTYPE_DIRECTORY))
return false;
ffStrbufSubstrAfterLastC(pkg, '/');
if (
ffStrbufStartsWithS(pkg, "nixos-system-nixos-") ||
ffStrbufEndsWithS(pkg, "-doc") ||
ffStrbufEndsWithS(pkg, "-man") ||
ffStrbufEndsWithS(pkg, "-info") ||
ffStrbufEndsWithS(pkg, "-dev") ||
ffStrbufEndsWithS(pkg, "-bin")
) return false;
enum { START, DIGIT, DOT, MATCH } state = START;
for (uint32_t i = 0; i < pkg->length; i++)
{
char c = pkg->chars[i];
switch (state)
{
case START:
if (c >= '0' && c <= '9')
state = DIGIT;
break;
case DIGIT:
if (c >= '0' && c <= '9')
continue;
if (c == '.')
state = DOT;
else
state = START;
break;
case DOT:
if (c >= '0' && c <= '9')
state = MATCH;
else
state = START;
break;
case MATCH:
break;
}
}
return state == MATCH;
}
static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count)
{
if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE))
return false;
FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreate();
if (!ffReadFileBuffer(cacheDir->chars, &cacheContent))
return false;
// Format: <hash>\n<count>
uint32_t split = ffStrbufFirstIndexC(&cacheContent, '\n');
if (split == cacheContent.length)
return false;
ffStrbufSetNS(hash, split, cacheContent.chars);
*count = (uint32_t)atoi(cacheContent.chars + split + 1);
return true;
}
static bool writeNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t count)
{
FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreateCopy(hash);
ffStrbufAppendF(&cacheContent, "\n%u", count);
return ffWriteFileBuffer(cacheDir->chars, &cacheContent);
}
static uint32_t getNixPackagesImpl(char* path)
{
//Nix detection is kinda slow, so we only do it if the dir exists
if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY))
return 0;
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(128);
FF_STRBUF_AUTO_DESTROY cacheDir = ffStrbufCreateCopy(&instance.state.platform.cacheDir);
ffStrbufEnsureEndsWithC(&cacheDir, '/');
ffStrbufAppendS(&cacheDir, "fastfetch/packages/nix");
ffStrbufAppendS(&cacheDir, path);
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(255);
ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq | wc -l");
//Check the hash first to determine if we need to recompute the count
FF_STRBUF_AUTO_DESTROY hash = ffStrbufCreateA(64);
FF_STRBUF_AUTO_DESTROY cacheHash = ffStrbufCreateA(64);
uint32_t count = 0;
ffProcessAppendStdOut(&output, (char* const[]) {
"sh",
"-c",
command.chars,
ffProcessAppendStdOut(&hash, (char* const[]) {
"nix-store",
"--query",
"--hash",
path,
NULL
});
return (uint32_t) strtol(output.chars, NULL, 10);
if (checkNixCache(&cacheDir, &cacheHash, &count) && ffStrbufEqual(&hash, &cacheHash))
return count;
//Cache is invalid, recompute the count
count = 0;
//Implementation based on bash script from here:
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024);
ffProcessAppendStdOut(&output, (char* const[]) {
"nix-store",
"--query",
"--requisites",
path,
NULL
});
uint32_t lineLength = 0;
for (uint32_t i = 0; i < output.length; i++)
{
if (output.chars[i] != '\n')
{
lineLength++;
continue;
}
output.chars[i] = '\0';
FFstrbuf line = {
.allocated = 0,
.length = lineLength,
.chars = output.chars + i - lineLength
};
if (isValidNixPkg(&line))
count++;
lineLength = 0;
}
writeNixCache(&cacheDir, &hash, count);
return count;
}
static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
@@ -315,6 +433,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
if (!(options->disabled & FF_PACKAGES_FLAG_PALUDIS_BIT)) packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
if (!(options->disabled & FF_PACKAGES_FLAG_OPKG_BIT)) packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->am = getAM(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_SORCERY_BIT)) packageCounts->sorcery += getNumStrings(baseDir, "/var/state/sorcery/packages", ":installed:");
}
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
@@ -383,7 +502,36 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
{
// check if ~/.nix-profile exists
FF_STRBUF_AUTO_DESTROY profilePath = ffStrbufCreateCopy(&baseDir);
ffStrbufAppendS(&profilePath, ".nix-profile");
if (ffPathExists(profilePath.chars, FF_PATHTYPE_DIRECTORY))
{
result->nixUser = getNixPackages(&baseDir, ".nix-profile");
}
// check if $XDG_STATE_HOME/nix/profile exists
else
{
FF_STRBUF_AUTO_DESTROY stateDir = ffStrbufCreate();
const char* stateHome = getenv("XDG_STATE_HOME");
if(ffStrSet(stateHome))
{
ffStrbufSetS(&stateDir, stateHome);
ffStrbufEnsureEndsWithC(&stateDir, '/');
}
else
{
ffStrbufSet(&stateDir, &instance.state.platform.homeDir);
ffStrbufAppendS(&stateDir, ".local/state/");
}
ffStrbufSet(&profilePath, &stateDir);
ffStrbufAppendS(&profilePath, "nix/profile");
result->nixUser = getNixPackages(&stateDir, "nix/profile");
}
}
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
}
+1 -1
View File
@@ -28,7 +28,7 @@ void ffPreparePublicIp(FFPublicIpOptions* options)
fputs("Error: only http: protocol is supported. Use `Command` module with `curl` if needed\n", stderr);
exit(1);
}
ffStrbufSubstrAfter(&host, hostStartIndex + (strlen("://") - 1));
ffStrbufSubstrAfter(&host, hostStartIndex + (uint32_t) (strlen("://") - 1));
}
uint32_t pathStartIndex = ffStrbufFirstIndexC(&host, '/');
+5 -14
View File
@@ -7,20 +7,11 @@
const char* ffDetectSwap(FFSwapResult* swap)
{
ULONG size = sizeof(SYSTEM_PAGEFILE_INFORMATION);
SYSTEM_PAGEFILE_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PAGEFILE_INFORMATION*)malloc(size);
while(true)
{
NTSTATUS status = NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size);
if(status == STATUS_INFO_LENGTH_MISMATCH)
{
if(!(pstart = (SYSTEM_PAGEFILE_INFORMATION*)realloc(pstart, size)))
return "realloc(pstart, size) failed";
}
else if(!NT_SUCCESS(status))
return "NtQuerySystemInformation(SystemPagefileInformation, size) failed";
break;
}
uint8_t buffer[1024];
ULONG size = sizeof(buffer);
SYSTEM_PAGEFILE_INFORMATION* pstart = (SYSTEM_PAGEFILE_INFORMATION*) buffer;
if(!NT_SUCCESS(NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size)))
return "NtQuerySystemInformation(SystemPagefileInformation, size) failed";
uint32_t pageSize = instance.state.platform.pageSize;
swap->bytesUsed = (uint64_t)pstart->TotalUsed * pageSize;
+4 -1
View File
@@ -228,7 +228,10 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
{
if (!instance.config.display.tsVersion) return false;
if(strcasecmp(exeName, "bash") == 0 || strcasecmp(exeName, "sh") == 0)
if(ffStrEqualsIgnCase(exeName, "sh")) // #849
return false;
if(strcasecmp(exeName, "bash") == 0)
return getShellVersionBash(exe, version);
if(strcasecmp(exeName, "zsh") == 0)
return getExeVersionGeneral(exe, version); //zsh 5.9 (arm-apple-darwin21.3.0)
@@ -243,6 +243,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrEquals(name, "perf") ||
ffStrEquals(name, "guake-wrapped") ||
ffStrEquals(name, "time") ||
ffStrEquals(name, "hyfetch") || //when hyfetch uses fastfetch as backend
ffStrContainsIgnCase(name, "debug") ||
ffStrContainsIgnCase(name, "not-found") ||
ffStrEndsWith(name, ".sh")
@@ -482,14 +483,12 @@ static void setShellInfoDetails(FFShellResult* result)
static void setTerminalInfoDetails(FFTerminalResult* result)
{
if(result->exeName[0] == '.' && ffStrEndsWith(result->exeName, "-wrapped"))
if(ffStrbufStartsWithC(&result->processName, '.') && ffStrbufEndsWithS(&result->processName, "-wrapped"))
{
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
// We use processName when detecting version and font, overriding it for simplification
ffStrbufSetNS(
&result->processName,
(uint32_t) (strlen(result->exeName) - strlen(".-wrapped")),
result->exeName + 1);
ffStrbufSubstrBefore(&result->processName, result->processName.length - (uint32_t) strlen("-wrapped"));
ffStrbufSubstrAfter(&result->processName, 0);
}
if(ffStrbufEqualS(&result->processName, "wezterm-gui"))
@@ -520,6 +519,11 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
else if(ffStrbufEqualS(&result->processName, "iTerm.app") || ffStrbufStartsWithS(&result->processName, "iTermServer-"))
ffStrbufInitStatic(&result->prettyName, "iTerm");
else if(ffStrbufEndsWithS(&result->exePath, "Terminal.app/Contents/MacOS/Terminal"))
{
ffStrbufSetStatic(&result->processName, "Apple_Terminal"); // for terminal font detection
ffStrbufInitStatic(&result->prettyName, "Apple Terminal");
}
else if(ffStrbufEqualS(&result->processName, "Apple_Terminal"))
ffStrbufInitStatic(&result->prettyName, "Apple Terminal");
else if(ffStrbufEqualS(&result->processName, "WarpTerminal"))
@@ -104,6 +104,7 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables
ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || // scoop warps the real binaries with a "shim" exe
ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "hyfetch") || // uses fastfetch as backend
ffStrbufContainIgnCaseS(&result->prettyName, "debug") ||
ffStrbufContainIgnCaseS(&result->prettyName, "time") ||
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014
+2 -1
View File
@@ -337,7 +337,8 @@ static const char* detectWifiWithIoctls(FFlist* result)
const char* ffDetectWifi(FFlist* result)
{
#ifdef FF_HAVE_LIBNM
if(!detectWifiWithLibnm(result))
detectWifiWithLibnm(result);
if(result->length) // NetworkManager not enabled? #811
return NULL;
#endif
+32 -33
View File
@@ -249,7 +249,7 @@ static void printCommandHelp(const char* command)
puts(FASTFETCH_DATATEXT_HELP_COLOR);
else if(ffStrEqualsIgnCase(command, "format"))
puts(FASTFETCH_DATATEXT_HELP_FORMAT);
else if(isalpha(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // <module>-format
else if(ffCharIsEnglishAlphabet(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // <module>-format
printCommandFormatHelp(command);
else if(!printSpecificCommandHelp(command))
fprintf(stderr, "Error: No specific help for command '%s' provided\n", command);
@@ -321,21 +321,42 @@ static void parseOption(FFdata* data, const char* key, const char* value);
static bool parseJsoncFile(const char* path)
{
yyjson_read_err error;
yyjson_doc* doc = yyjson_read_file(path, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, &error);
if (!doc)
assert(!instance.state.configDoc);
{
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
yyjson_read_err error;
instance.state.configDoc = yyjson_read_file(path, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, &error);
if (!instance.state.configDoc)
{
fprintf(stderr, "Error: failed to parse JSON config file `%s` at pos %zu: %s\n", path, error.pos, error.msg);
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
{
fprintf(stderr, "Error: failed to parse JSON config file `%s` at pos %zu: %s\n", path, error.pos, error.msg);
exit(477);
}
return false;
}
}
{
const char* error = NULL;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
if (!yyjson_is_obj(root))
error = "Invalid JSON config format. Root value must be an object";
if (
error ||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
(error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) ||
false
) {
fprintf(stderr, "JsonConfig Error: %s\n", error);
exit(477);
}
return false;
}
if (instance.state.configDoc)
yyjson_doc_free(instance.state.configDoc); // for `--load-config`
instance.state.configDoc = doc;
return true;
}
@@ -779,27 +800,6 @@ static void parseArguments(FFdata* data, int argc, char** argv, void (*parser)(F
static void run(FFdata* data)
{
if (instance.state.configDoc)
{
const char* error = NULL;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
if (!yyjson_is_obj(root))
error = "Invalid JSON config format. Root value must be an object";
if (
error ||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
(error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) ||
false
) {
fprintf(stderr, "JsonConfig Error: %s\n", error);
exit(477);
}
}
const bool useJsonConfig = data->structure.length == 0 && instance.state.configDoc;
if (useJsonConfig)
@@ -863,6 +863,7 @@ static void writeConfigFile(FFdata* data, const FFstrbuf* filename)
int main(int argc, char** argv)
{
ffInitInstance();
atexit(ffDestroyInstance);
//Data stores things only needed for the configuration of fastfetch
FFdata data = {
@@ -888,6 +889,4 @@ int main(int argc, char** argv)
ffStrbufDestroy(&customValue->value);
}
ffListDestroy(&data.customValues);
ffDestroyInstance();
}
+22
View File
@@ -0,0 +1,22 @@
..
`:]x**j-,'
.,+t***********z\<"
?******************;
'*n` .'`^,;;,^`'. ,cc.
-<. .[l
// ^^ ^^ \\
!^ $2^^$1 ":
'tt}` $2!~]rj_$1 ")t/.
Itttt?' $2~~]rr]$1 `{tttt,
\tttttt!""I$2_]r($1"""~tttttt1
'_tttttttttttt$2)f$1tttttttttttti.
\*ztttttttttttttttttttttttttf**[
l**c)tttttttttttttttttttttttt(z**,
.z*x.`tttttttttttttttttttttttt.`u*n
>` (tttttttttttttttttttttt] "I
,tttttttttttttttttttttt`
./ttttt$2f$1tttttttt$2f$1ttttt(
'I)$2))(\()($1tt$2))|\()($1{;'
$2.~~~~~~~|)~~~~~~~<$1
'$2[)))))1$1|($2)))))))$1?
$2",,," ",,,^
+14
View File
@@ -0,0 +1,14 @@
█ █ █ █ █ █ █ █ █ █ █
███████████████████████
▄▄██ ██▄▄
▄▄██ ███████████ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ █████████████ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██ ██ ██▄▄
▄▄██ ██▄▄
███████████████████████
█ █ █ █ █ █ █ █ █ █ █
+19
View File
@@ -0,0 +1,19 @@
.''''....''''.
.''... ...''.
''.. ..''
'.. ..''
.'. .,,'.. .',,,' ..'.
.'. .,,,,' .,,,,,' .'.
.'. .,,,,' .,,,,,. .'.
'.. .,,,,'',,,,;. .''
.'. .,,,,,,,;;. ..'
.'. .,,,,;;;;;${c2}, ${c1}..'.
'.. .,;;;,${c2}';;;;;, ${c1}..'
.'. .;;${c2};;' .;;:::: ${c1}.,.
'.. ${c2}.;;;;' .::::::. ${c1}.,'
'.. ${c2}.;;;;' .::::::. ${c1}.,${c2}'${c1}
.'.. ${c2}.',.
${c1}',.. ${c2}.','
${c1}.,,... ${c2}..',,.
..,,''........',,,.
......
+18
View File
@@ -0,0 +1,18 @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@%*+--:------=+*%@@@@@@@@@@@@
@@@@@@@@@#=. .-+#%@@@@@%#*+--=#@@@@@@@@@
@@@@@@@+. .=%@@@@@@@@@@@@@@@@*-:+@@@@@@@
@@@@@*. *@@@@@@@@@@@@@@@@@@@@@%-.*@@@@@
@@@@- -@@@@@@@@@@@@@@@@@@@@@@@#: -@@@@
@@@: -@@@@@@@=.*@@@@@@@@@@@@%- = :@@@
@@= .@@@@@@@@%- :%@@@@@@@@@+ -%@# =@@
@% +@@@@@@@@@@#. =@@@@@@*. .*@@@@. %@
@+ *@@@@@@*..*@@+ *@@%- =@@@@@@- +@
@= *@@@@%- -%@@- := -%@@@@@@@: +@
@+ :@@@= +@@= .#@@@@@@@@% *@
@% +*. .: *@@#: +@@: @@
@@+ :%@- :- :: +@@
@@@- .=@@= -@@@
@@+. . +@@
%=..:.................::...........:..-%
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-1
View File
@@ -18,4 +18,3 @@
.:ooooooolc:. .ooooooooooo'
.':loooooo; ,oooooooooc
..';::c' .;loooo:'
.
+57 -11
View File
@@ -209,6 +209,7 @@ static const FFlogo A[] = {
// AoscOsRetro_small
{
.names = {"Aosc OS/Retro_small", "aoscosretro_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_AOSCOSRETRO_SMALL,
.colors = {
FF_COLOR_FG_BLUE,
@@ -375,6 +376,24 @@ static const FFlogo A[] = {
.colorKeys = FF_COLOR_FG_CYAN,
.colorTitle = FF_COLOR_FG_CYAN,
},
// Armbian
{
.names = {"Armbian"},
.lines = FASTFETCH_DATATEXT_LOGO_ARMBIAN,
.colors = {
FF_COLOR_FG_WHITE,
FF_COLOR_FG_RED,
},
},
// Armbian2
{
.names = {"Armbian2"},
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_ARMBIAN2,
.colors = {
FF_COLOR_FG_RED,
},
},
// Artix
{
.names = {"artix", "artixlinux", "artix-linux"},
@@ -764,6 +783,7 @@ static const FFlogo C[] = {
// CalinixOSSmall
{
.names = {"Calinix_small", "calinixos_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_CALINIXOS_SMALL,
.colors = {
FF_COLOR_FG_MAGENTA,
@@ -875,7 +895,7 @@ static const FFlogo C[] = {
// Chimera Linux
{
.names = {"Chimera Linux"},
.lines = FASTFETCH_DATATEXT_LOGO_CHIMERALINUX,
.lines = FASTFETCH_DATATEXT_LOGO_CHIMERA_LINUX,
.colors = {
FF_COLOR_FG_RED,
FF_COLOR_FG_MAGENTA,
@@ -1241,9 +1261,9 @@ static const FFlogo D[] = {
.colorKeys = FF_COLOR_FG_RED,
.colorTitle = FF_COLOR_FG_WHITE,
},
// Drauger
// DraugerOS
{
.names = {"Drauger"},
.names = {"DraugerOS", "Drauger"},
.lines = FASTFETCH_DATATEXT_LOGO_DRAUGER,
.colors = {
FF_COLOR_FG_RED,
@@ -1336,8 +1356,8 @@ static const FFlogo E[] = {
// EndeavourSmall
{
.names = {"Endeavour_small", "endeavour-linux_small", "endeavouros_small", "endeavouros-linux_small"},
.lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL,
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL,
.colors = {
FF_COLOR_FG_RED,
FF_COLOR_FG_MAGENTA,
@@ -1823,6 +1843,7 @@ static const FFlogo G[] = {
// GuixSmall
{
.names = {"Guix_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_GUIX_SMALL,
.colors = {
FF_COLOR_FG_YELLOW,
@@ -2089,6 +2110,15 @@ static const FFlogo K[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_WHITE,
},
// KernelOS
{
.names = {"KernelOS"},
.lines = FASTFETCH_DATATEXT_LOGO_KERNELOS,
.colors = {
FF_COLOR_FG_RED,
FF_COLOR_FG_MAGENTA,
}
},
// KDENeon
{
.names = {"KDE", "kde-neon"},
@@ -2462,6 +2492,7 @@ static const FFlogo M[] = {
// MageiaSmall
{
.names = {"Mageia_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_MAGEIA_SMALL,
.colors = {
FF_COLOR_FG_CYAN,
@@ -2649,7 +2680,7 @@ static const FFlogo M[] = {
},
// MX
{
.names = {"MX"},
.names = {"MX", "MX Linux"},
.lines = FASTFETCH_DATATEXT_LOGO_MX,
.colors = {
FF_COLOR_FG_WHITE,
@@ -2659,7 +2690,8 @@ static const FFlogo M[] = {
},
// MXSmall
{
.names = {"MX_small", "mx-small"},
.names = {"MX_small", "mx linux_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_MX_SMALL,
.colors = {
FF_COLOR_FG_WHITE,
@@ -2667,6 +2699,17 @@ static const FFlogo M[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_CYAN,
},
// MX2
{
.names = {"MX2"},
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_MX2,
.colors = {
FF_COLOR_FG_WHITE,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_CYAN,
},
// LAST
{},
};
@@ -2730,6 +2773,7 @@ static const FFlogo N[] = {
// NixOSSmall
{
.names = {"NixOS_small", "nix_small", "nixos-linux-small", "nix-linux-small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_NIXOS_SMALL,
.colors = {
FF_COLOR_FG_BLUE,
@@ -2962,7 +3006,7 @@ static const FFlogo O[] = {
},
// OpenMandriva
{
.names = {"openmandriva", "open-mandriva", "open_mandriva"},
.names = {"openmandriva", "open-mandriva", "open_mandriva", "openmandriva lx"},
.lines = FASTFETCH_DATATEXT_LOGO_OPENMANDRIVA,
.colors = {
FF_COLOR_FG_BLUE,
@@ -3301,6 +3345,7 @@ static const FFlogo P[] = {
// PostMarketOSSmall
{
.names = {"PostMarketOS_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_POSTMARKETOS_SMALL,
.colors = {
FF_COLOR_FG_GREEN,
@@ -3309,7 +3354,7 @@ static const FFlogo P[] = {
},
// Proxmox
{
.names = {"proxmox"},
.names = {"Proxmox", "pve"},
.lines = FASTFETCH_DATATEXT_LOGO_PROXMOX,
.colors = {
FF_COLOR_FG_WHITE,
@@ -3560,6 +3605,7 @@ static const FFlogo R[] = {
// RockyLinuxSmall
{
.names = {"rocky_small", "rocky-linux_small", "rockylinux_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_ROCKY_SMALL,
.colors = {
FF_COLOR_FG_GREEN,
@@ -3791,14 +3837,14 @@ static const FFlogo S[] = {
FF_COLOR_FG_WHITE,
},
},
// SourceMage
// Source Mage
{
.names = {"Source Mage", "source_mage"},
.names = {"Source Mage", "Source Mage GNU/Linux", "source_mage", "sourcemage"},
.lines = FASTFETCH_DATATEXT_LOGO_SOURCE_MAGE,
.colors = {
FF_COLOR_FG_WHITE,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorKeys = FF_COLOR_FG_RED,
.colorTitle = FF_COLOR_FG_WHITE,
},
// Solaris
+32 -7
View File
@@ -1,6 +1,7 @@
#include "image.h"
#include "common/io/io.h"
#include "common/printing.h"
#include "util/stringUtils.h"
#include <limits.h>
#include <math.h>
@@ -53,13 +54,14 @@ static FFstrbuf base64Encode(const FFstrbuf* in)
return out;
}
static bool printImageIterm(void)
static bool printImageIterm(bool printError)
{
const FFOptionsLogo* options = &instance.config.logo;
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if(!ffAppendFileBuffer(options->source.chars, &buf))
{
fputs("Logo: Failed to load image file\n", stderr);
if (printError)
fputs("Logo (iterm): Failed to load image file\n", stderr);
return false;
}
@@ -134,9 +136,17 @@ static bool printImageIterm(void)
return true;
}
static bool printImageKittyDirect(void)
static bool printImageKittyDirect(bool printError)
{
const FFOptionsLogo* options = &instance.config.logo;
if (!ffPathExists(options->source.chars, FF_PATHTYPE_FILE))
{
if (printError)
fputs("Logo (kitty-direct): Failed to load image file\n", stderr);
return false;
}
FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&options->source);
if (!options->width || !options->height)
@@ -771,7 +781,7 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
if(!getCharacterPixelDimensions(&requestData))
{
if(printError)
fputs("Logo: getCharacterPixelDimensions() failed", stderr);
fputs("Logo: getCharacterPixelDimensions() failed\n", stderr);
return false;
}
@@ -788,7 +798,7 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
//We can safely return here, because if realpath failed, we surely won't be able to read the file
ffStrbufDestroy(&requestData.cacheDir);
if(printError)
fputs("Logo: Querying realpath of the image source failed", stderr);
fputs("Logo: Querying realpath of the image source failed\n", stderr);
return false;
}
ffStrbufRecalculateLength(&requestData.cacheDir);
@@ -832,6 +842,13 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
bool ffLogoPrintImageIfExists(FFLogoType type, bool printError)
{
if(instance.config.display.pipe)
{
if(printError)
fputs("Logo: Image logo is not supported in pipe mode\n", stderr);
return false;
}
if(!ffPathExists(instance.config.logo.source.chars, FF_PATHTYPE_FILE))
{
if(printError)
@@ -839,11 +856,19 @@ bool ffLogoPrintImageIfExists(FFLogoType type, bool printError)
return false;
}
const char* term = getenv("TERM");
if((term && ffStrEquals(term, "screen")) || getenv("ZELLIJ"))
{
if(printError)
fputs("Logo: Image logo is not supported in terminal multiplexers\n", stderr);
return false;
}
if(type == FF_LOGO_TYPE_IMAGE_ITERM)
return printImageIterm();
return printImageIterm(printError);
if(type == FF_LOGO_TYPE_IMAGE_KITTY_DIRECT)
return printImageKittyDirect();
return printImageKittyDirect(printError);
#if !defined(FF_HAVE_CHAFA)
if(type == FF_LOGO_TYPE_IMAGE_CHAFA)
+26 -16
View File
@@ -61,7 +61,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048);
if (instance.config.display.brightColor)
if (!instance.config.display.pipe && instance.config.display.brightColor)
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT);
ffStrbufAppendNC(&result, options->paddingTop, '\n');
@@ -70,7 +70,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
instance.state.logoHeight = options->paddingTop;
//Use logoColor[0] as the default color
if(doColorReplacement)
if(doColorReplacement && !instance.config.display.pipe)
ffStrbufAppendF(&result, "\e[%sm", options->colors[0].chars);
while(*data != '\0')
@@ -143,19 +143,27 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
continue;
}
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
int index = ((int) *data) - 49;
//If the index is valid, print the color. Otherwise continue as normal
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
if(!instance.config.display.pipe)
{
ffStrbufAppendC(&result, '$');
++currentlineLength;
//Don't continue here, we want to print the current char as unicode
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
int index = ((int) *data) - 49;
//If the index is valid, print the color. Otherwise continue as normal
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
{
ffStrbufAppendC(&result, '$');
++currentlineLength;
//Don't continue here, we want to print the current char as unicode
}
else
{
ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars);
++data;
continue;
}
}
else
{
ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars);
++data;
continue;
}
@@ -188,7 +196,8 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
}
}
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
if(!instance.config.display.pipe)
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
if(!options->separate)
{
@@ -393,7 +402,8 @@ static bool logoPrintFileIfExists(bool doColorReplacement, bool raw)
: !ffAppendFileBuffer(options->source.chars, &content)
)
{
fprintf(stderr, "Logo: Failed to load file content from logo source: %s \n", options->source.chars);
if (instance.config.display.showErrors)
fprintf(stderr, "Logo: Failed to load file content from logo source: %s \n", options->source.chars);
return false;
}
@@ -448,7 +458,7 @@ static bool logoTryKnownType(void)
if(options->type == FF_LOGO_TYPE_IMAGE_RAW)
return logoPrintFileIfExists(false, true);
return logoPrintImageIfExists(options->type, true);
return logoPrintImageIfExists(options->type, instance.config.display.showErrors);
}
static void logoPrintKnownType(void)
@@ -459,10 +469,10 @@ static void logoPrintKnownType(void)
void ffLogoPrint(void)
{
//In pipe mode, we don't have a logo or padding.
//When generate JSON result, we don't have a logo or padding.
//We also don't need to set main color, because it won't be printed anyway.
//So we can return quickly here.
if(instance.config.display.pipe || instance.state.resultDoc)
if(instance.state.resultDoc)
{
instance.state.logoHeight = 0;
instance.state.logoWidth = 0;
+19 -14
View File
@@ -84,23 +84,28 @@ void ffPrintBattery(FFBatteryOptions* options)
if (error)
{
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
return;
}
else
if(results.length == 0)
{
for(uint8_t i = 0; i < (uint8_t) results.length; i++)
{
FFBatteryResult* result = ffListGet(&results, i);
printBattery(options, result, i);
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found");
return;
}
ffStrbufDestroy(&result->manufacturer);
ffStrbufDestroy(&result->modelName);
ffStrbufDestroy(&result->technology);
ffStrbufDestroy(&result->status);
ffStrbufDestroy(&result->serial);
ffStrbufDestroy(&result->manufactureDate);
}
if(results.length == 0)
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No batteries found");
for(uint32_t i = 0; i < results.length; i++)
{
FFBatteryResult* result = ffListGet(&results, i);
printBattery(options, result, (uint8_t) i);
}
FF_LIST_FOR_EACH(FFBatteryResult, result, results)
{
ffStrbufDestroy(&result->manufacturer);
ffStrbufDestroy(&result->modelName);
ffStrbufDestroy(&result->technology);
ffStrbufDestroy(&result->status);
ffStrbufDestroy(&result->serial);
ffStrbufDestroy(&result->manufactureDate);
}
}
+10 -12
View File
@@ -150,19 +150,17 @@ void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options,
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
else
{
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFBluetoothResult, item, results)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address);
yyjson_mut_obj_add_uint(doc, obj, "battery", item->battery);
yyjson_mut_obj_add_bool(doc, obj, "connected", item->connected);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "type", &item->type);
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFBluetoothResult, item, results)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address);
yyjson_mut_obj_add_uint(doc, obj, "battery", item->battery);
yyjson_mut_obj_add_bool(doc, obj, "connected", item->connected);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "type", &item->type);
}
FF_LIST_FOR_EACH(FFBluetoothResult, device, results)
-6
View File
@@ -154,12 +154,6 @@ void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options
return;
}
if(result.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "No result is detected.");
return;
}
yyjson_mut_val* arr = yyjson_mut_arr(doc);
yyjson_mut_obj_add_val(doc, module, "result", arr);
+8 -7
View File
@@ -16,9 +16,6 @@ static inline uint8_t max(uint8_t a, uint8_t b)
void ffPrintColors(FFColorsOptions* options)
{
if(instance.config.display.pipe)
return;
bool flag = false;
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(128);
@@ -28,7 +25,8 @@ void ffPrintColors(FFColorsOptions* options)
// 3%d: Set the foreground color
for(uint8_t i = options->block.range[0]; i <= min(options->block.range[1], 7); i++)
{
ffStrbufAppendF(&result, "\e[3%dm", i);
if(!instance.config.display.pipe)
ffStrbufAppendF(&result, "\e[3%dm", i);
for (uint8_t j = 0; j < options->block.width; j++)
ffStrbufAppendS(&result, "");
}
@@ -40,7 +38,8 @@ void ffPrintColors(FFColorsOptions* options)
if(options->paddingLeft > 0)
ffPrintCharTimes(' ', options->paddingLeft);
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
if(!instance.config.display.pipe)
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
ffStrbufPutTo(&result, stdout);
ffStrbufClear(&result);
}
@@ -49,7 +48,8 @@ void ffPrintColors(FFColorsOptions* options)
// 9%d: Set the foreground to the bright color
for(uint8_t i = max(options->block.range[0], 8); i <= options->block.range[1]; i++)
{
ffStrbufAppendF(&result, "\e[1;9%dm", i - 8);
if(!instance.config.display.pipe)
ffStrbufAppendF(&result, "\e[1;9%dm", i - 8);
for (uint8_t j = 0; j < options->block.width; j++)
ffStrbufAppendS(&result, "");
}
@@ -82,7 +82,8 @@ void ffPrintColors(FFColorsOptions* options)
if(options->paddingLeft > 0)
ffPrintCharTimes(' ', options->paddingLeft);
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
if(!instance.config.display.pipe)
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
ffStrbufPutTo(&result, stdout);
}
+2 -7
View File
@@ -6,15 +6,10 @@
void ffPrintCustom(FFCustomOptions* options)
{
if (options->moduleArgs.outputFormat.length == 0)
{
ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "output format must be set for custom module");
return;
}
ffPrintLogoAndKey(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&options->moduleArgs.outputFormat, stdout);
puts(FASTFETCH_TEXT_MODIFIER_RESET);
if(!instance.config.display.pipe)
puts(FASTFETCH_TEXT_MODIFIER_RESET);
}
bool ffParseCustomCommandOptions(FFCustomOptions* options, const char* key, const char* value)
+1 -1
View File
@@ -152,7 +152,7 @@ void ffGenerateDateTimeJsonConfig(FFDateTimeOptions* options, yyjson_mut_doc* do
void ffGenerateDateTimeJsonResult(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
yyjson_mut_obj_add_uint(doc, module, "result", ffTimeGetNow());
yyjson_mut_obj_add_strcpy(doc, module, "result", ffTimeToFullStr(ffTimeGetNow()));
}
void ffPrintDateTimeHelpFormat(void)
+9 -52
View File
@@ -131,54 +131,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
}
}
static void printMountpoint(FFDiskOptions* options, const FFlist* disks, const char* mountpoint)
{
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
{
if(ffStrbufEqualS(&disk->mountpoint, mountpoint))
{
printDisk(options, disk);
return;
}
}
ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disk found for mountpoint: %s", mountpoint);
}
static void printMountpoints(FFDiskOptions* options, const FFlist* disks)
{
#ifdef _WIN32
const char separator = ';';
#else
const char separator = ':';
#endif
FF_STRBUF_AUTO_DESTROY mountpoints = ffStrbufCreateCopy(&options->folders);
ffStrbufTrim(&mountpoints, separator);
uint32_t startIndex = 0;
while(startIndex < mountpoints.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&mountpoints, startIndex, separator);
mountpoints.chars[colonIndex] = '\0';
printMountpoint(options, disks, mountpoints.chars + startIndex);
startIndex = colonIndex + 1;
}
}
static void printAutodetected(FFDiskOptions* options, const FFlist* disks)
{
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
{
if(disk->type & ~options->showTypes)
continue;
printDisk(options, disk);
}
}
void ffPrintDisk(FFDiskOptions* options)
{
FF_LIST_AUTO_DESTROY disks = ffListCreate(sizeof (FFDisk));
@@ -190,10 +142,13 @@ void ffPrintDisk(FFDiskOptions* options)
}
else
{
if(options->folders.length == 0)
printAutodetected(options, &disks);
else
printMountpoints(options, &disks);
FF_LIST_FOR_EACH(FFDisk, disk, disks)
{
if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes))
continue;
printDisk(options, disk);
}
}
FF_LIST_FOR_EACH(FFDisk, disk, disks)
@@ -451,6 +406,8 @@ void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso
yyjson_mut_arr_add_str(doc, typeArr, "Hidden");
if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT)
yyjson_mut_arr_add_str(doc, typeArr, "Read-only");
if(item->type & FF_DISK_VOLUME_TYPE_UNKNOWN_BIT)
yyjson_mut_arr_add_str(doc, typeArr, "Unknown");
const char* pstr = ffTimeToFullStr(item->createTime);
if (*pstr)
+1
View File
@@ -279,6 +279,7 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs
yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect display");
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFDisplayResult, item, dsResult->displays)
{
-6
View File
@@ -118,12 +118,6 @@ void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
return;
}
if(!result.length)
{
yyjson_mut_obj_add_str(doc, module, "error", "No devices detected");
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
{
+1 -8
View File
@@ -334,13 +334,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs
if(error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
goto exit;
}
if(results.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "Failed to detect any IPs");
goto exit;
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
@@ -354,7 +348,6 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs
yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name);
}
exit:
FF_LIST_FOR_EACH(FFLocalIpResult, ip, results)
{
ffStrbufDestroy(&ip->name);
+1 -9
View File
@@ -22,7 +22,7 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
ffStrbufAppend(result, &instance.state.platform.systemName);
//Append code name if it is missing
if(os->codename.length > 0 && !ffStrbufContain(result, &os->versionID))
if(os->codename.length > 0 && !ffStrbufContain(result, &os->codename))
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &os->codename);
@@ -40,14 +40,6 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
ffStrbufAppend(result, &os->version);
}
#ifdef __APPLE__
if(os->buildID.length > 0)
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &os->buildID);
}
#endif
//Append variant if it is missing
if(os->variant.length > 0 && ffStrbufFirstIndex(result, &os->variant) == result->length)
{
+1
View File
@@ -27,6 +27,7 @@ typedef enum FFPackagesFlags
FF_PACKAGES_FLAG_WINGET_BIT = 1 << 17,
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
FF_PACKAGES_FLAG_AM_BIT = 1 << 19,
FF_PACKAGES_FLAG_SORCERY_BIT = 1 << 20,
} FFPackagesFlags;
typedef struct FFPackagesOptions
+18 -2
View File
@@ -4,7 +4,7 @@
#include "modules/packages/packages.h"
#include "util/stringUtils.h"
#define FF_PACKAGES_NUM_FORMAT_ARGS 26
#define FF_PACKAGES_NUM_FORMAT_ARGS 30
void ffPrintPackages(FFPackagesOptions* options)
{
@@ -65,11 +65,15 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE(winget)
FF_PRINT_PACKAGE(opkg)
FF_PRINT_PACKAGE(am)
FF_PRINT_PACKAGE(sorcery)
putchar('\n');
}
else
{
uint32_t nixAll = counts.nixDefault + counts.nixSystem + counts.nixUser;
uint32_t flatpakAll = counts.flatpakSystem + counts.flatpakUser;
uint32_t brewAll = counts.brew + counts.brewCask;
FF_PRINT_FORMAT_CHECKED(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_PACKAGES_NUM_FORMAT_ARGS, ((FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &counts.all},
{FF_FORMAT_ARG_TYPE_UINT, &counts.pacman},
@@ -97,6 +101,10 @@ void ffPrintPackages(FFPackagesOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &counts.winget},
{FF_FORMAT_ARG_TYPE_UINT, &counts.opkg},
{FF_FORMAT_ARG_TYPE_UINT, &counts.am},
{FF_FORMAT_ARG_TYPE_UINT, &counts.sorcery},
{FF_FORMAT_ARG_TYPE_UINT, &nixAll},
{FF_FORMAT_ARG_TYPE_UINT, &flatpakAll},
{FF_FORMAT_ARG_TYPE_UINT, &brewAll},
}));
}
@@ -166,6 +174,7 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
case 'S': if (false);
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(SORCERY)
break;
case 'W': if (false);
FF_TEST_PACKAGE_NAME(WINGET)
@@ -266,6 +275,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
case 'S': if (false);
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(SORCERY)
break;
case 'W': if (false);
FF_TEST_PACKAGE_NAME(WINGET)
@@ -316,6 +326,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
FF_TEST_PACKAGE_NAME(AM)
FF_TEST_PACKAGE_NAME(SORCERY)
#undef FF_TEST_PACKAGE_NAME
}
}
@@ -362,12 +373,13 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
FF_APPEND_PACKAGE_COUNT(xbps)
FF_APPEND_PACKAGE_COUNT(opkg)
FF_APPEND_PACKAGE_COUNT(am)
FF_APPEND_PACKAGE_COUNT(sorcery)
yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch);
}
void ffPrintPackagesHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
"Number of all packages",
"Number of pacman packages",
"Pacman branch on manjaro",
@@ -394,6 +406,10 @@ void ffPrintPackagesHelpFormat(void)
"Number of winget packages",
"Number of opkg packages",
"Number of am packages",
"Number of sorcery packages",
"Total number of all nix packages",
"Total number of all flatpak packages",
"Total number of all brew packages",
}));
}
+2 -3
View File
@@ -107,7 +107,6 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options)
ffTempsAppendNum(dev->temperature, &tempStr, options->tempConfig);
if (dev->type & FF_PHYSICALDISK_TYPE_READWRITE)
readOnlyType = "Read-write";
ffParseSize(dev->size, &buffer);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_PHYSICALDISK_NUM_FORMAT_ARGS, ((FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &buffer},
{FF_FORMAT_ARG_TYPE_STRBUF, &dev->name},
@@ -118,7 +117,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options)
{FF_FORMAT_ARG_TYPE_STRING, removableType},
{FF_FORMAT_ARG_TYPE_STRING, readOnlyType},
{FF_FORMAT_ARG_TYPE_STRBUF, &dev->revision},
{FF_FORMAT_ARG_TYPE_DOUBLE, &tempStr},
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr},
}));
}
++index;
@@ -252,7 +251,7 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut
void ffPrintPhysicalDiskHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PHYSICALDISK_MODULE_NAME, "{1}", FF_PHYSICALDISK_NUM_FORMAT_ARGS, ((const char* []) {
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PHYSICALDISK_MODULE_NAME, "{1} [{6}, {7}, {8}]", FF_PHYSICALDISK_NUM_FORMAT_ARGS, ((const char* []) {
"Device size (formatted)",
"Device name",
"Device interconnect type",
+18 -14
View File
@@ -101,24 +101,28 @@ void ffGeneratePowerAdapterJsonResult(FF_MAYBE_UNUSED FFPowerAdapterOptions* opt
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
else if(results.length == 0)
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results)
{
yyjson_mut_obj_add_str(doc, module, "error", "No power adapters found");
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "description", &item->description);
yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &item->manufacturer);
yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &item->modelName);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &item->serial);
yyjson_mut_obj_add_int(doc, obj, "watts", item->watts);
}
else
FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results)
{
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "description", &item->description);
yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &item->manufacturer);
yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &item->modelName);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &item->serial);
yyjson_mut_obj_add_int(doc, obj, "watts", item->watts);
}
ffStrbufDestroy(&item->manufacturer);
ffStrbufDestroy(&item->description);
ffStrbufDestroy(&item->modelName);
ffStrbufDestroy(&item->name);
ffStrbufDestroy(&item->serial);
}
}
+15 -4
View File
@@ -12,9 +12,20 @@ static inline uint32_t max(uint32_t a, uint32_t b)
static inline uint32_t getWcsWidth(const FFstrbuf* mbstr, wchar_t* wstr, mbstate_t* state)
{
int result = 1;
for (uint32_t i = 0; i < mbstr->length; i++)
{
if (!isascii(mbstr->chars[i]))
{
result = 0;
break;
}
}
if (__builtin_expect(result, 1)) return mbstr->length;
const char* str = mbstr->chars;
uint32_t wstrLength = (uint32_t) mbsrtowcs(wstr, &str, mbstr->length, state);
int result = mk_wcswidth(wstr, wstrLength);
result = mk_wcswidth(wstr, wstrLength);
return result > 0 ? (uint32_t) result : mbstr->length;
}
@@ -32,9 +43,9 @@ void ffPrintSeparator(FFSeparatorOptions* options)
+ (fqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name
ffLogoPrintLine();
if(options->string.length == 0)
if(__builtin_expect(options->string.length == 1, 1))
{
ffPrintCharTimes('-', titleLength);
ffPrintCharTimes(options->string.chars[0], titleLength);
}
else
{
@@ -131,7 +142,7 @@ void ffInitSeparatorOptions(FFSeparatorOptions* options)
NULL,
ffGenerateSeparatorJsonConfig
);
ffStrbufInit(&options->string);
ffStrbufInitStatic(&options->string, "-");
}
void ffDestroySeparatorOptions(FFSeparatorOptions* options)
-6
View File
@@ -200,12 +200,6 @@ void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_m
return;
}
if(result.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "No active sound devices found");
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFSoundDevice, item, result)
{
+1 -2
View File
@@ -146,7 +146,7 @@ void ffGenerateUsersJsonResult(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_m
if(error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
goto exit;
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
@@ -164,7 +164,6 @@ void ffGenerateUsersJsonResult(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_m
yyjson_mut_obj_add_null(doc, obj, "loginTime");
}
exit:
FF_LIST_FOR_EACH(FFUserResult, user, results)
{
ffStrbufDestroy(&user->clientIp);
-5
View File
@@ -114,11 +114,6 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
if(!result.length)
{
yyjson_mut_obj_add_str(doc, module, "error", "No Wifi interfaces found");
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFWifiResult, wifi, result)
+3 -4
View File
@@ -92,7 +92,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
}
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->percentNdigits = (uint8_t) yyjson_get_uint(ndigits);
if (ndigits) options->sizeNdigits = (uint8_t) yyjson_get_uint(ndigits);
}
else if (ffStrEqualsIgnCase(key, "temp"))
{
@@ -350,16 +350,15 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options)
ffStrbufInitStatic(&options->keyValueSeparator, ": ");
options->showErrors = false;
options->pipe = !isatty(STDOUT_FILENO);
options->pipe = !isatty(STDOUT_FILENO) || !!getenv("NO_COLOR");
#ifdef NDEBUG
options->disableLinewrap = !options->pipe;
options->hideCursor = !options->pipe;
#else
options->disableLinewrap = false;
options->hideCursor = false;
#endif
options->hideCursor = false;
options->binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
options->sizeNdigits = 2;
options->sizeMaxPrefix = UINT8_MAX;
+1 -1
View File
@@ -27,7 +27,7 @@ typedef struct FFOptionsDisplay
FFstrbuf keyValueSeparator;
bool stat;
bool pipe; //disables logo and all escape sequences
bool pipe; //disables all escape sequences
bool showErrors;
bool disableLinewrap;
bool hideCursor;
-9
View File
@@ -27,8 +27,6 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
options->escapeBedrock = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "playerName"))
ffStrbufSetS(&options->playerName, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "osFile"))
ffStrbufSetS(&options->osFile, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
{
if (yyjson_is_str(val))
@@ -79,8 +77,6 @@ bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key
options->escapeBedrock = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--player-name"))
ffOptionParseString(key, value, &options->playerName);
else if (ffStrEqualsIgnCase(key, "--os-file"))
ffOptionParseString(key, value, &options->osFile);
else if(ffStrEqualsIgnCase(key, "--ds-force-drm"))
{
if (ffOptionParseBoolean(value))
@@ -109,7 +105,6 @@ void ffOptionsInitGeneral(FFOptionsGeneral* options)
#if defined(__linux__) || defined(__FreeBSD__)
options->escapeBedrock = true;
ffStrbufInit(&options->playerName);
ffStrbufInit(&options->osFile);
options->dsForceDrm = FF_DS_FORCE_DRM_TYPE_FALSE;
#elif defined(_WIN32)
options->wmiTimeout = 5000;
@@ -120,7 +115,6 @@ void ffOptionsDestroyGeneral(FF_MAYBE_UNUSED FFOptionsGeneral* options)
{
#if defined(__linux__) || defined(__FreeBSD__)
ffStrbufDestroy(&options->playerName);
ffStrbufDestroy(&options->osFile);
#endif
}
@@ -145,9 +139,6 @@ void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_do
if (!ffStrbufEqual(&options->playerName, &defaultOptions.playerName))
yyjson_mut_obj_add_strbuf(doc, obj, "playerName", &options->playerName);
if (!ffStrbufEqual(&options->osFile, &defaultOptions.osFile))
yyjson_mut_obj_add_strbuf(doc, obj, "osFile", &options->osFile);
if (options->dsForceDrm != defaultOptions.dsForceDrm)
{
switch (options->dsForceDrm)
-1
View File
@@ -17,7 +17,6 @@ typedef struct FFOptionsGeneral
// Module options that cannot be put in module option structure
#if defined(__linux__) || defined(__FreeBSD__)
FFstrbuf playerName;
FFstrbuf osFile;
bool escapeBedrock;
FFDsForceDrmType dsForceDrm;
#elif defined(_WIN32)
+2 -2
View File
@@ -73,8 +73,8 @@ void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial
{
if (edid[17] > 0 && edid[17] < 0xFF)
{
*year = edid[17] + 1990;
*week = edid[16];
*year = (uint16_t) edid[17] + 1990;
*week = (uint16_t) edid[16];
if (*week == 0xFF) *week = 0;
}
else
+5
View File
@@ -69,3 +69,8 @@ static inline bool ffStrContainsC(const char* str, char compareTo)
{
return strchr(str, compareTo) != NULL;
}
static inline bool ffCharIsEnglishAlphabet(char c)
{
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
}
+1 -1
View File
@@ -5,6 +5,6 @@
#define FASTFETCH_TEXT_MODIFIER_BOLT "\033[1m"
#define FASTFETCH_TEXT_MODIFIER_ERROR "\033[1;31m"
#define FASTFETCH_TEXT_MODIFIER_RESET "\033[0m"
#define FASTFETCH_TEXT_MODIFIER_RESET "\033[m"
#endif