Compare commits

..

107 Commits

Author SHA1 Message Date
github-action-benchmark c89f042658 add Fastfetch (customSmallerIsBetter) benchmark result for 44b32e9f84 2026-10-30 00:55:37 +00:00
github-action-benchmark e7eb20c5d1 add Fastfetch (customSmallerIsBetter) benchmark result for 06957877a8 2026-10-29 06:43:49 +00:00
github-action-benchmark cfad568f11 add Fastfetch (customSmallerIsBetter) benchmark result for 2f68ce7f74 2026-10-28 01:25:29 +00:00
github-action-benchmark da8d815091 add Fastfetch (customSmallerIsBetter) benchmark result for 197d1c6e5d 2026-10-24 16:26:05 +00:00
github-action-benchmark 00071a09ea add Fastfetch (customSmallerIsBetter) benchmark result for bfe74b8437 2026-10-23 07:35:05 +00:00
github-action-benchmark f348047572 add Fastfetch (customSmallerIsBetter) benchmark result for bbb92543b0 2026-10-17 02:30:18 +00:00
github-action-benchmark 92cfbca21d add Fastfetch (customSmallerIsBetter) benchmark result for 99785f54dd 2026-10-16 08:49:09 +00:00
github-action-benchmark 486aebef1b Update benchmark dashboard 2026-10-14 07:40:16 +00:00
github-action-benchmark 52aee15e4a add Fastfetch (customSmallerIsBetter) benchmark result for 17bb3fd238 2026-10-14 07:40:14 +00:00
Carter Li f8a86e81fc remove unwanted data 2026-10-14 14:55:57 +08:00
github-action-benchmark f512f1d6e0 add Fastfetch (customSmallerIsBetter) benchmark result for 1d8bbeb89f 2026-10-14 06:16:52 +00:00
github-action-benchmark 0de4da81a3 add Fastfetch (customSmallerIsBetter) benchmark result for cb73fdcfc9 2026-10-13 19:07:38 +00:00
github-action-benchmark 3c7fb1f9b9 add Fastfetch (customSmallerIsBetter) benchmark result for a9ee641bd6 2026-10-13 16:03:07 +00:00
github-action-benchmark acf92a2ef7 add Fastfetch (customSmallerIsBetter) benchmark result for f93ffed57a 2026-10-13 10:54:52 +00:00
github-action-benchmark b77a093e6f add Fastfetch (customSmallerIsBetter) benchmark result for 73ebe95120 2026-10-13 03:57:32 +00:00
github-action-benchmark 63bdcb0f35 add Fastfetch (customSmallerIsBetter) benchmark result for fe05a041ef 2026-10-12 21:17:32 +00:00
github-action-benchmark 98793fe054 add Fastfetch (customSmallerIsBetter) benchmark result for b7bc8ca99d 2026-10-12 10:25:27 +00:00
github-action-benchmark 7f9459e026 add Fastfetch (customSmallerIsBetter) benchmark result for 3b042d26ab 2026-10-11 19:25:14 +00:00
github-action-benchmark 20e3898b85 add Fastfetch (customSmallerIsBetter) benchmark result for 3453de61f8 2026-10-11 07:52:43 +00:00
github-action-benchmark c2ee3c1e73 add Fastfetch (customSmallerIsBetter) benchmark result for ad1d12ed38 2026-10-11 06:54:37 +00:00
github-action-benchmark 7a46e5beb3 add Fastfetch (customSmallerIsBetter) benchmark result for 3ccaf2d7dd 2026-10-11 03:25:51 +00:00
github-action-benchmark 4f6fee46e1 add Fastfetch (customSmallerIsBetter) benchmark result for 1f32e0bcb2 2026-10-10 19:37:25 +00:00
github-action-benchmark e759ede8c2 add Fastfetch (customSmallerIsBetter) benchmark result for cc435d2b70 2026-10-10 15:15:15 +00:00
github-action-benchmark f9d27680c1 add Fastfetch (customSmallerIsBetter) benchmark result for e0361fdcf6 2026-10-10 11:58:18 +00:00
github-action-benchmark ce2fe55520 add Fastfetch (customSmallerIsBetter) benchmark result for 262a8ca4d3 2026-10-09 15:27:39 +00:00
github-action-benchmark a6143d137f add Fastfetch (customSmallerIsBetter) benchmark result for 35a35f066c 2026-10-07 06:51:20 +00:00
github-action-benchmark 2945a5fb60 add Fastfetch (customSmallerIsBetter) benchmark result for 66709ccc77 2026-10-07 01:17:03 +00:00
github-action-benchmark 0fc21a0fbd add Fastfetch (customSmallerIsBetter) benchmark result for 3a069b2331 2026-10-05 05:43:48 +00:00
github-action-benchmark 4edf655ad2 add Fastfetch (customSmallerIsBetter) benchmark result for 845d5983aa 2026-10-05 05:38:50 +00:00
github-action-benchmark 293dbcf017 add Fastfetch (customSmallerIsBetter) benchmark result for 6e2a25759d 2026-10-04 11:14:53 +00:00
github-action-benchmark 4df181b2f8 add Fastfetch (customSmallerIsBetter) benchmark result for 9ac3822105 2026-10-03 11:15:14 +00:00
github-action-benchmark d395c82fa1 add Fastfetch (customSmallerIsBetter) benchmark result for ae1288d087 2026-10-03 04:57:43 +00:00
github-action-benchmark 9c3d5cd91b add Fastfetch (customSmallerIsBetter) benchmark result for b201fd2db9 2026-10-03 03:12:25 +00:00
github-action-benchmark f622f34259 add Fastfetch (customSmallerIsBetter) benchmark result for 5f65515c3c 2026-10-02 18:01:38 +00:00
github-action-benchmark 3d3783a21d add Fastfetch (customSmallerIsBetter) benchmark result for 54dcb1b6f9 2026-10-02 16:07:31 +00:00
github-action-benchmark 7a921954ac add Fastfetch (customSmallerIsBetter) benchmark result for 39d667d1d5 2026-10-02 15:47:49 +00:00
github-action-benchmark c55ee1cd4f add Fastfetch (customSmallerIsBetter) benchmark result for 782b7b8fd1 2026-10-02 12:34:12 +00:00
github-action-benchmark 57e480b497 add Fastfetch (customSmallerIsBetter) benchmark result for a9bf53b4a1 2026-10-02 12:27:08 +00:00
github-action-benchmark 2e5437dc78 add Fastfetch (customSmallerIsBetter) benchmark result for ab200636f1 2026-10-01 13:20:04 +00:00
github-action-benchmark 9db01a1422 add Fastfetch (customSmallerIsBetter) benchmark result for 4d8d6a5fe9 2026-09-30 15:45:51 +00:00
github-action-benchmark a979fc2616 add Fastfetch (customSmallerIsBetter) benchmark result for 47fbfcb0e9 2026-09-29 16:53:02 +00:00
github-action-benchmark 13b2892888 add Fastfetch (customSmallerIsBetter) benchmark result for c88ec3bcc3 2026-09-29 16:10:15 +00:00
github-action-benchmark 57e65da3f9 add Fastfetch (customSmallerIsBetter) benchmark result for ffbf4ec7ac 2026-09-29 05:39:21 +00:00
github-action-benchmark 13d76a3c1b add Fastfetch (customSmallerIsBetter) benchmark result for a3f46d9742 2026-09-29 02:27:01 +00:00
github-action-benchmark b37a5c2f65 add Fastfetch (customSmallerIsBetter) benchmark result for 4fb57bb39b 2026-09-28 15:21:24 +00:00
github-action-benchmark cf452ce3b1 add Fastfetch (customSmallerIsBetter) benchmark result for cdbe8f54c6 2026-09-28 01:31:38 +00:00
github-action-benchmark 1ace3a0309 add Fastfetch (customSmallerIsBetter) benchmark result for 676dbcfee2 2026-09-27 00:44:53 +00:00
github-action-benchmark 88095e2fee add Fastfetch (customSmallerIsBetter) benchmark result for 9801d89316 2026-09-26 10:29:25 +00:00
github-action-benchmark a0e9635c02 add Fastfetch (customSmallerIsBetter) benchmark result for fb52d32452 2026-09-26 06:32:30 +00:00
github-action-benchmark d80828fd10 add Fastfetch (customSmallerIsBetter) benchmark result for 866c5e89c8 2026-09-25 10:30:44 +00:00
github-action-benchmark efde3c6e54 add Fastfetch (customSmallerIsBetter) benchmark result for 3a9595e121 2026-09-23 15:09:26 +00:00
github-action-benchmark 1fce90fc89 add Fastfetch (customSmallerIsBetter) benchmark result for f8df95d146 2026-09-23 14:49:10 +00:00
github-action-benchmark 6c1b658baf add Fastfetch (customSmallerIsBetter) benchmark result for 592ef68d60 2026-09-23 10:23:33 +00:00
github-action-benchmark 20af5266ca add Fastfetch (customSmallerIsBetter) benchmark result for 9e99d07d16 2026-09-23 07:41:09 +00:00
github-action-benchmark 34e4412ee1 add Fastfetch (customSmallerIsBetter) benchmark result for 7f3209181e 2026-09-21 17:09:58 +00:00
github-action-benchmark 3263f4862a add Fastfetch (customSmallerIsBetter) benchmark result for 2f74d6be4d 2026-09-21 14:33:36 +00:00
github-action-benchmark 446df99cff add Fastfetch (customSmallerIsBetter) benchmark result for aaa9153f5a 2026-09-21 07:30:40 +00:00
github-action-benchmark 38cefd6076 add Fastfetch (customSmallerIsBetter) benchmark result for 203ccb31fa 2026-09-21 05:59:54 +00:00
github-action-benchmark 1480ceb9f3 add Fastfetch (customSmallerIsBetter) benchmark result for eda38a37ba 2026-09-20 16:13:53 +00:00
github-action-benchmark 4bafc33edc add Fastfetch (customSmallerIsBetter) benchmark result for 39564acde4 2026-09-20 13:13:50 +00:00
github-action-benchmark 7f2fd75f63 add Fastfetch (customSmallerIsBetter) benchmark result for 3bfc4ec674 2026-09-20 12:05:11 +00:00
github-action-benchmark b49612a131 add Fastfetch (customSmallerIsBetter) benchmark result for fea55b276e 2026-09-20 08:41:36 +00:00
github-action-benchmark f665ae598d add Fastfetch (customSmallerIsBetter) benchmark result for 58692adabc 2026-09-19 00:14:27 +00:00
github-action-benchmark dc16401bdd add Fastfetch (customSmallerIsBetter) benchmark result for f8fd708423 2026-09-17 11:30:41 +00:00
github-action-benchmark 1bba03c12d add Fastfetch (customSmallerIsBetter) benchmark result for c23c98a85a 2026-09-17 08:56:50 +00:00
github-action-benchmark 4b6ea0cf1a add Fastfetch (customSmallerIsBetter) benchmark result for 43988a8d41 2026-09-17 06:46:41 +00:00
github-action-benchmark 1dfa6a39f7 add Fastfetch (customSmallerIsBetter) benchmark result for 9bac273165 2026-09-16 16:42:48 +00:00
github-action-benchmark 0ae93f7ef4 add Fastfetch (customSmallerIsBetter) benchmark result for d1b747192f 2026-09-16 12:56:33 +00:00
github-action-benchmark 400a29b374 add Fastfetch (customSmallerIsBetter) benchmark result for 02dc6a4428 2026-09-15 15:09:23 +00:00
github-action-benchmark e35b950d55 add Fastfetch (customSmallerIsBetter) benchmark result for 3d7ea720fb 2026-09-14 15:02:37 +00:00
github-action-benchmark 47f7c45ee6 add Fastfetch (customSmallerIsBetter) benchmark result for 35ffdb3995 2026-09-14 11:15:50 +00:00
github-action-benchmark baaa02e526 add Fastfetch (customSmallerIsBetter) benchmark result for d796945604 2026-09-14 11:02:05 +00:00
github-action-benchmark e66adcaa39 add Fastfetch (customSmallerIsBetter) benchmark result for cd5a2def9a 2026-09-13 09:42:03 +00:00
github-action-benchmark 5191ab89d8 add Fastfetch (customSmallerIsBetter) benchmark result for 8334035927 2026-09-13 04:39:08 +00:00
github-action-benchmark 67827c0295 add Fastfetch (customSmallerIsBetter) benchmark result for ec8b9be354 2026-09-13 03:22:59 +00:00
github-action-benchmark 7be0d8e716 add Fastfetch (customSmallerIsBetter) benchmark result for 61e3f6108c 2026-09-12 15:46:24 +00:00
github-action-benchmark d964776f65 add Fastfetch (customSmallerIsBetter) benchmark result for eff8514536 2026-09-11 16:20:43 +00:00
github-action-benchmark b28170d5af add Fastfetch (customSmallerIsBetter) benchmark result for 222fe7e3f9 2026-09-09 06:30:02 +00:00
github-action-benchmark 8d531e36e7 add Fastfetch (customSmallerIsBetter) benchmark result for 7d0256fb85 2026-09-08 12:54:21 +00:00
github-action-benchmark 0c651a697a add Fastfetch (customSmallerIsBetter) benchmark result for a70c37fdaf 2026-09-07 03:18:35 +00:00
github-action-benchmark 29bb196e0c add Fastfetch (customSmallerIsBetter) benchmark result for 66e9e38f28 2026-09-06 15:44:05 +00:00
github-action-benchmark 5c74223282 add Fastfetch (customSmallerIsBetter) benchmark result for 5d290cc3d5 2026-09-05 12:31:10 +00:00
github-action-benchmark 3e5ac19cd4 add Fastfetch (customSmallerIsBetter) benchmark result for 2e542bea64 2026-09-05 05:59:09 +00:00
github-action-benchmark 97ff3a9f86 add Fastfetch (customSmallerIsBetter) benchmark result for c708b6f5cd 2026-09-04 16:55:21 +00:00
github-action-benchmark 2735fd6674 add Fastfetch (customSmallerIsBetter) benchmark result for ecee5694fb 2026-09-04 11:55:31 +00:00
github-action-benchmark f498a58b5a add Fastfetch (customSmallerIsBetter) benchmark result for 4e78f1b703 2026-09-04 10:27:45 +00:00
github-action-benchmark fdbcdc7faa add Fastfetch (customSmallerIsBetter) benchmark result for 62f78ca60c 2026-09-03 07:43:45 +00:00
github-action-benchmark 562c80b183 add Fastfetch (customSmallerIsBetter) benchmark result for dbd681b779ac4e4f1c5ad3df580ace4aaedfb29d 2026-09-03 02:27:01 +00:00
github-action-benchmark 36cfa77ccc add Fastfetch (customSmallerIsBetter) benchmark result for ce61783c4b 2026-09-03 02:07:38 +00:00
github-action-benchmark c9e50c80fc add Fastfetch (customSmallerIsBetter) benchmark result for 20597bff00 2026-09-02 09:16:26 +00:00
github-action-benchmark 4a482f333c add Fastfetch (customSmallerIsBetter) benchmark result for 90a6e90b19 2026-09-02 02:54:38 +00:00
github-action-benchmark d54eea5e64 add Fastfetch (customSmallerIsBetter) benchmark result for 2787d97973 2026-09-01 11:32:06 +00:00
github-action-benchmark bc2d37f398 add Fastfetch (customSmallerIsBetter) benchmark result for 0b1bc5b527 2026-09-01 06:24:29 +00:00
github-action-benchmark 9f1d38f1fa add Fastfetch (customSmallerIsBetter) benchmark result for 4863a173e4 2026-08-31 16:49:06 +00:00
github-action-benchmark aa21823c4e add Fastfetch (customSmallerIsBetter) benchmark result for b0ba084b5e 2026-08-31 14:35:06 +00:00
github-action-benchmark cc906cd866 add Fastfetch (customSmallerIsBetter) benchmark result for 9c791b2c12 2026-08-31 08:09:22 +00:00
github-action-benchmark 56c64bc643 add Fastfetch (customSmallerIsBetter) benchmark result for 5b1ad1008d 2026-08-31 00:48:24 +00:00
github-action-benchmark 6a10dab4c3 add Fastfetch (customSmallerIsBetter) benchmark result for 39024abae9 2026-08-30 12:04:57 +00:00
github-action-benchmark c0371c1f32 add Fastfetch (customSmallerIsBetter) benchmark result for 4dba32aabb 2026-08-30 11:12:06 +00:00
github-action-benchmark 83849aeefb add Fastfetch (customSmallerIsBetter) benchmark result for 753ddec3c5 2026-08-29 12:27:12 +00:00
github-action-benchmark bed3578808 add Fastfetch (customSmallerIsBetter) benchmark result for 3abcf4195f 2026-08-29 04:23:21 +00:00
github-action-benchmark 0c39fc4dcb add Fastfetch (customSmallerIsBetter) benchmark result for 7fe08bddd0 2026-08-28 17:12:57 +00:00
github-action-benchmark d028d57a79 add Fastfetch (customSmallerIsBetter) benchmark result for 4d00dc6802 2026-08-28 02:00:28 +00:00
github-action-benchmark 215c6bd78f add Fastfetch (customSmallerIsBetter) benchmark result for d7de7c41ca 2026-08-27 07:37:15 +00:00
github-action-benchmark 6a25eaa82b add Fastfetch (customSmallerIsBetter) benchmark result for d80fe3f004 2026-08-27 07:06:53 +00:00
github-action-benchmark 24256e8592 add Fastfetch (customSmallerIsBetter) benchmark result for 49331cd9671fcc916aa168d0864b3c73ee271629 2026-08-27 14:25:24 +08:00
Carter Li cf0bdb1055 Initialize gh-pages 2026-08-27 13:40:13 +08:00
317 changed files with 228703 additions and 28153 deletions
-17
View File
@@ -1,17 +0,0 @@
root = true
[*]
end_of_line = lf
indent_style = space
tab_width = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.{md,fflogo}]
trim_trailing_whitespace = false
[*.{fflogo}]
insert_final_newline = false
[*.yml]
tab_width = 2
-2
View File
@@ -1,2 +0,0 @@
*.h linguist-language=c
*.c linguist-language=c
-1
View File
@@ -1 +0,0 @@
github: LinusDierheimer
-43
View File
@@ -1,43 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
# General description of bug:
# Often helpful questions:
* Does the issue occur across multiple terminal emulators? [Y/N]
* Does the issue occur across multiple shells? (bash, zsh, fish, etc) [Y/N]
Output of `fastfetch --version`:
```
//paste here
```
Output of `fastfetch --load-config devinfo`:
```
//paste here
```
Output of `fastfetch --load-config devinfo-verbose`:
<!--
Note that this output will contain you public IP. If it is not relevant for the issue, feel free to remove it before uploading.
-->
```
//paste here
```
Output of `fastfetch --list-features`:
```
//paste here
```
<!--
If you get the following error: `Error: couldn't find config: [...]`, copy the files in [presets](../../presets/) to `/usr/share/fastfetch/presets/` or `~/.local/share/fastfetch/presets/`.
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --multithreading false --disable-linewrap false`.
-->
-14
View File
@@ -1,14 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
# Current state:
# Wanted state:
# Why the change is sensible:
-18
View File
@@ -1,18 +0,0 @@
---
name: Logo request
about: Request a new logo
title: ''
labels: logo request
assignees: ''
---
# OS
```
paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
```
# Ascii
```
paste ascii art here. If you leave this empty, i will try to find the logo myself.
```
-302
View File
@@ -1,302 +0,0 @@
name: manage pushes
on:
- push
- pull_request
jobs:
linux:
name: Linux
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
outputs:
ffversion: ${{ steps.ffversion.outputs.ffversion }}
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
- name: build project
run: cmake --build . --target package
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
- name: get fastfetch version
id: ffversion
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-linux
path: ./fastfetch-*.*
macos:
name: MacOS
runs-on: macos-latest
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: install required packages
run: brew install vulkan-loader molten-vk imagemagick chafa
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --target package
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-macos
path: ./fastfetch-*.*
freebsd:
name: FreeBSD
runs-on: macos-12
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: run VM
uses: vmactions/freebsd-vm@v0
with:
prepare: |
pkg install -y cmake git pkgconf pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package
time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
time ./flashfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-freebsd
path: ./fastfetch-*.*
windows:
name: Windows
runs-on: windows-latest
permissions:
security-events: write
contents: read
defaults:
run:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: CLANG64
update: true
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
- name: print msys version
run: uname -a
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
- name: create OpenCL.pc
run: |
cat > /clang64/lib/pkgconfig/OpenCL.pc << EOF
prefix=/clang64
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenCL
Description: Open Computing Language generic Installable Client Driver Loader
Version: 2022.09.30-1
Libs: -L${libdir} -lOpenCL.dll
Cflags: -I${includedir}
EOF
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c, cpp
- name: configure project
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build .
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: copy necessary dlls
run: cp /clang64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
- name: create zip archive
run: zip fastfetch-windows.zip *.dll fastfetch.exe flashfetch.exe
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-windows
path: ./fastfetch-windows.zip
windows-old:
name: Windows-old
runs-on: windows-latest
permissions:
security-events: write
contents: read
defaults:
run:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: git zip mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-cjson mingw-w64-x86_64-vulkan-loader mingw-w64-x86_64-opencl-icd
- name: print msys version
run: uname -a
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
- name: create OpenCL.pc
run: |
cat > /mingw64/lib/pkgconfig/OpenCL.pc << EOF
prefix=/mingw64
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenCL
Description: Open Computing Language generic Installable Client Driver Loader
Version: 2022.09.30-1
Libs: -L${libdir} -lOpenCL.dll
Cflags: -I${includedir}
EOF
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c, cpp
- name: configure project
run: env PKG_CONFIG_PATH=/mingw64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_BUFFER=Off .
- name: build project
run: cmake --build .
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: copy necessary dlls
run: cp /mingw64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
- name: create zip archive
run: zip fastfetch-windows-old.zip *.dll fastfetch.exe flashfetch.exe
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-windows-old
path: ./fastfetch-windows-old.zip
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch'
name: Release
runs-on: ubuntu-latest
needs:
- linux
- macos
- freebsd
- windows
permissions:
contents: write
steps:
- name: download artifacts
uses: actions/download-artifact@v3
- name: get latest release version
id: get_version_release
uses: pozetroninc/github-action-get-latest-release@master
with:
repository: ${{ github.repository }}
- name: create release
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ needs.linux.outputs.ffversion }}
commit: ${{ github.sha }}
artifactErrorsFailBuild: true
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*
+3 -9
View File
@@ -1,9 +1,3 @@
**/build/
**/.vscode/
**/.cache/
**/.kdev4/
**/.DS_Store
/.vs
cscope.*
tags
fastfetch.kdev4
/.cache
/.vscode
/build*
-221
View File
@@ -1,221 +0,0 @@
# 1.8.1
Notable Changes:
* `Song` was used as an alias to `Media` module. It's removed to avoid confusion. All song related flags (`--song-key`, etc) should change to media (`--media-key`, etc). (@CarterLi)
Bugfixes:
* Mountpoint paths on linux get decoded correctly (#364)
* Color parsing once again works (@IanManske, #365)
* Using a custom key with a placeholder for the local ip module now does work correctly if multiple interfaces are present (#368)
# 1.8.0
This release introduces Windows support! Fastfetch now fully support all major desktop OSes (Linux, macOS, Windows and FreeBSD)
Notable Changes:
* Bios / Board / Chassis modules are splitted against Host module for performance reasons
* Caching is removed. Option `--nocache` is removed accordingly
Features:
* Windows (7 and newer) is officially and fully supported
* FreeBSD support is improved greatly (Bios, Cpu Temp, Cpu Usage, Disk, Host, Processes, Swap, Terminal / Shell, Uptime)
* Adds a new flag `--stat`, which prints time usage for individual modules
* Adds Wifi module which supports Windows and macOS
* Adds data source option for logo printing
* Detects Homebrew Cellar and Cask seperately
* Detects WSL version
* Detects disk based on mount point
* Exposes more chafa configs
* Improves performance for Cpu Usage, Public IP, Weather modules
* Improves performance for Kitty image protocol when both image width / height specified
* Improves performance for large file loading
* Improves performance for macOS WM and Host detection
* Improves shell and terminal detection on macOS
* Supports Deepin Terminal terminal font
* Supports GPU detection on Android
* Supports Kitty Terminal terminal font
* Supports bar output for percentage values
* Supports Bios module on macOS
* Supports eopkg package manager detection
* Supports iTerm image logo protocol
* Supports image logo printing on macOS
* Supports tcsh version detection
* Vulkan module on macOS no longer requires vulkan-loader to work
Logos:
* Alpine
* CRUX
* EndeavourOS
* Enso
* Garuda small
* Nobara
* OpenMandriva
* Parabola GNU/Linux-libre
* Rocky
* Rosa
* Solus
* Univalent
* Vanilla OS
Bugfixes:
* Fixes disk size detection on 32bit Linux (#337)
* Fixes cpu freq detection in WSL
* Fixes internal bug of FFstrbuf
* Fixes some memory leaks
* Fixes segfault if 0 is given as argument index
* Lots of code refactors
# 1.7.5
Fixes a crash on linux that could happen when getting zsh version (#285)
# 1.7.4
The last element in the default structure (currently the color blocks) is now printed again (#283)
# 1.7.3
A lot of small improvements for MacOS & BSD platforms.
Features:
* BSD is now officially supported (#228)
* MacPorts package manager support (@SladeGetz, #234)
* Battery support for MacOS (@CarterLi, #235)
* Processes, swap & terminal font support for MacOS(@CarterLi, #237)
* Media support for MacOS (@CarterLi, #242)
* Player support for MacOS (@CarterLi, #245)
* WM theme support for MacOS (@CarterLi, #246)
* CPU usage support for MacOS (@CarterLi, #247)
* Power Adapter module (@CarterLi, #249)
* Windows terminal font for WSL (@CarterLi, #254)
* Temps & Font support for MacOS (@CarterLi, #258)
* Terminal font support for Termux (@CarterLi, #263)
* Weather module (@CarterLi, #266)
Logos
* Crystal linux (@AloneER0, #239)
* FreeBSD (@draumaz, #244)
* New Ubuntu (@AloneER0, #259)
Bugfixes:
* Don't segfault in GPU code on Intel Macs (@CarterLi, #236)
* Don't use hardcoded size units in presets (@dr460nf1r3, #255)
* Don't crash with some format strings (#252)
* --logo-none keeps key color now (#264)
# 1.7.2
Fixes the bash completions
# 1.7.1
This release brings a lot of bug fixes and improvements for MacOS. Big thanks to @CarterLi for the help on this!
Features:
* The color of the title and the keys can now be configured individually, using `--color-keys` and `--color-title` respectively. Some distros have different defaults now, similar to neofetch
* Swap module, similar to the Memory module, but for swap. Add `Swap` to your structure to enable it (#225)
Logos:
* Slackware (#227)
Bugfixes:
* Used disk space is now calculated much more accurately
* On Linux, GPU names are no longer truncated, if they are longer than 32 characters (#224)
* On Linux, NVIDIA GPUs once again have a proper name
* On M1 platforms, showing the GPU name no longer crashes the program (#222)
* Brew package count does now work on M1 platforms too
* The Vulkan module now does work on MacOS too
* The OpenGL and OpenCL modules now work on MacOS too (@CarterLi, #226)
* The LocalIp module now works on MacOS too (@CarterLi, #232)
* Detecting custom WMs on MacOS does now work
Other:
* GitHub actions now builds a dmg file for MacOS, as you can see in the release page
# 1.7.0
This release brings support for MacOS!
The basics things are working, but it is far from feature parity with Linux.
I developed this in a VM, so bugs on real hardware are likely.
If you have a Mac and no idea what to do with your free time, i am very happy to accept pull requests / work on issues.
A lot of things were changed under the hood to make this possible, which should bring better performance and stability on all platforms.
Besides that, the following things have changed:
Features:
* The binary prefix used can now be configured, and is used consistently across all modules. Set `--binary-prefix` to `iec` (default), `si` or `jedec`.
* AMD GPUs now have a much better name, if the file `/usr/share/libdrm/amdgpu.ids` exists. For example my dedicated GPU, which was displayed as `AMD/ATI Radeon RX 5600 OEM/5600 XT / 5700/5700 XT`, is now `AMD Radeon RX 5600M`.
Logos:
* MacOS
* CachyOS small (@sirlucjan, #220)
* MSYS2 (#219)
Bugfixes:
* the `--file` option, which can be used to display the contents of a file as the logo, is now working again.
# 1.6.5
Fixes parsing quoted values in config files
# 1.6.4
Releasing this, so fedora can package fastfetch. Thanks to @jonathanspw for doing that!
Features:
* --set-keyless option (#215)
* Replace `\n`, `\t`, `\e` and `\\` in user provided strings, just like c would do it (#215)
* APK (Alpine Package Keeper) support (@mxkrsv, #216)
Logos:
* Alma Linux (@jonathanspw, #214)
Bugfixes:
* replace deprecated gethostbyname call with getaddrinfo (#217)
# 1.6.3
Fixes installing presets in their own directory (@ceamac, #212)
# 1.6.2
Releasing this, so void linux can package fastfetch.
Logos:
* Rosa linux (#206)
* KISS linux (@draumaz, #207)
* LangitKetujuh (@hervyqa, #208)
Bugfixes:
* Using musl as libc does work now (#210)
* XBPS packages are once again printed (#209)
* configured target dirs are applied to install directories too
* empty XDG_* env vars don't cause a crash anymore
# 1.6.1
Fixes build on android (#205)
# 1.6.0
Features:
* Detect QT on more DEs than just KDE Plasma. The [Plasma] category was therefore renamed to [QT]
* Alacritty font detection
* Load `/etc/fastfetch/config.conf` before user config
* Disk: print one decimal point if size < 100GB
* `--title-fqdn` option, to print fully qualified domain name instead of host name in title
Logos:
* updated old NixOS logo
Bugfixes:
* Correctly detect GTK on DEs that store their settings in dconf
* Correctly detect NixOS packages
* Mutter WM detected once again
* Show full NixOS version in OS output
* Don't segfault if an invalid structure is given
* WSL doesn't output GPU anymore, as the name is always meaningless
-807
View File
@@ -1,807 +0,0 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 1.8.1
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
)
set(PROJECT_LICENSE "MIT license")
###################
# Target Platform #
###################
if(ANDROID)
set(LINUX FALSE)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Ll]inux.*")
set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Bb][Ss][Dd].*")
set(BSD TRUE CACHE BOOL "..." FORCE)
elseif(NOT APPLE AND NOT WIN32)
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()
if(WIN32)
enable_language(CXX)
endif()
#############################
# Compile time dependencies #
#############################
set(THREADS_PREFER_PTHREAD_FLAG NOT WIN32)
find_package(Threads)
find_package(PkgConfig)
if(NOT PKG_CONFIG_FOUND)
message(WARNING "pkg-config not found, library detection might be limited")
endif()
include(CheckIncludeFile)
#####################
# Configure options #
#####################
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE" OFF)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF)
cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF)
cmake_dependent_option(USE_WIN_GPU_DXGI "Use DXGI to detect GPUs instead of WMI. Faster, but may ignore GPUs that only support DX9" ON "WIN32" OFF)
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
####################
# Compiler options #
####################
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
if(ENABLE_THREADS)
if(CMAKE_USE_WIN32_THREADS_INIT)
message(STATUS "Threads type: Win32 thread")
elseif(CMAKE_USE_PTHREADS_INIT)
message(STATUS "Threads type: pthread")
endif()
else()
message(STATUS "Threads type: disabled")
endif()
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
if(WIN32)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti")
endif()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
if(NOT WIN32)
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic")
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
#######################
# Target FS structure #
#######################
if(NOT TARGET_DIR_ROOT)
if(NOT ANDROID)
set(TARGET_DIR_ROOT "")
else()
set(TARGET_DIR_ROOT "/data/data/com.termux/files/usr")
endif()
endif()
if(NOT TARGET_DIR_USR)
if(NOT ANDROID)
set(TARGET_DIR_USR "${TARGET_DIR_ROOT}/usr")
else()
set(TARGET_DIR_USR "${TARGET_DIR_ROOT}")
endif()
endif()
if(NOT TARGET_DIR_HOME)
if(APPLE)
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/Users")
elseif(ANDROID)
set(TARGET_DIR_HOME "/data/data/com.termux/files/home")
else()
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/home")
endif()
endif()
if(NOT TARGET_DIR_ETC)
set(TARGET_DIR_ETC "${TARGET_DIR_ROOT}/etc")
endif()
#https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${TARGET_DIR_USR}" CACHE PATH "..." FORCE)
endif()
if(NOT CMAKE_INSTALL_SYSCONFDIR)
set(CMAKE_INSTALL_SYSCONFDIR "${TARGET_DIR_ETC}" CACHE PATH "..." FORCE)
endif()
#################
# Tweak version #
#################
if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git describe --tags
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE PROJECT_VERSION_TWEAK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
endif()
if(PROJECT_VERSION_TWEAK)
string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}")
else()
set(PROJECT_VERSION_TWEAK_NUM 0)
endif()
#############
# Text data #
#############
function(fastfetch_load_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
string(REPLACE "\n" "\\n" TEMP "${TEMP}") # Replace newlines with \n
string(REPLACE "\"" "\\\"" TEMP "${TEMP}") # Replace quotes with \"
string(REPLACE "$\\" "" TEMP "${TEMP}") # Remove $\, so we can unescape some things
set("${OUTVAR}" "${TEMP}" PARENT_SCOPE)
endfunction(fastfetch_load_text)
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
fastfetch_load_text(src/data/config_system.txt DATATEXT_CONFIG_SYSTEM)
fastfetch_load_text(src/data/config_user.txt DATATEXT_CONFIG_USER)
fastfetch_load_text(src/data/modules.txt DATATEXT_MODULES)
fastfetch_load_text(src/data/help.txt DATATEXT_HELP)
fastfetch_load_text(src/data/help_color.txt DATATEXT_HELP_COLOR)
fastfetch_load_text(src/data/help_format.txt DATATEXT_HELP_FORMAT)
fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG)
######################
# Configure config.h #
######################
configure_file(src/fastfetch_config.h.in fastfetch_config.h)
#######################
# libfastfetch target #
#######################
set(LIBFASTFETCH_SRC
src/common/bar.c
src/common/font.c
src/common/format.c
src/common/init.c
src/common/io.c
src/common/library.c
src/common/parsing.c
src/common/printing.c
src/common/properties.c
src/common/settings.c
src/detection/cpu/cpu.c
src/detection/cpuUsage/cpuUsage.c
src/detection/datetime.c
src/detection/disk/disk.c
src/detection/displayserver/displayserver.c
src/detection/font/font.c
src/detection/gpu/gpu.c
src/detection/host/host.c
src/detection/locale/locale.c
src/detection/media/media.c
src/detection/os/os.c
src/detection/packages/packages.c
src/detection/terminalfont/terminalfont.c
src/detection/terminalshell/terminalshell.c
src/detection/title.c
src/detection/vulkan.c
src/logo/builtin.c
src/logo/image/im6.c
src/logo/image/im7.c
src/logo/image/image.c
src/logo/logo.c
src/modules/battery.c
src/modules/bios.c
src/modules/board.c
src/modules/break.c
src/modules/chassis.c
src/modules/colors.c
src/modules/cpu.c
src/modules/cpuUsage.c
src/modules/cursor.c
src/modules/custom.c
src/modules/date.c
src/modules/datetime.c
src/modules/de.c
src/modules/disk.c
src/modules/font.c
src/modules/gpu.c
src/modules/host.c
src/modules/icons.c
src/modules/kernel.c
src/modules/locale.c
src/modules/localip.c
src/modules/memory.c
src/modules/opencl.c
src/modules/opengl.c
src/modules/os.c
src/modules/packages.c
src/modules/player.c
src/modules/poweradapter.c
src/modules/processes.c
src/modules/publicip.c
src/modules/resolution.c
src/modules/separator.c
src/modules/shell.c
src/modules/media.c
src/modules/terminal.c
src/modules/terminalfont.c
src/modules/theme.c
src/modules/time.c
src/modules/title.c
src/modules/uptime.c
src/modules/users.c
src/modules/vulkan.c
src/modules/weather.c
src/modules/wifi.c
src/modules/wm.c
src/modules/wmtheme.c
src/util/FFlist.c
src/util/FFstrbuf.c
src/util/FFvaluestore.c
)
if(LINUX)
list(APPEND LIBFASTFETCH_SRC
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_linux.c
src/detection/bios/bios_linux.c
src/detection/board/board_linux.c
src/detection/chassis/chassis_linux.c
src/detection/cpu/cpu_linux.c
src/detection/cpuUsage/cpuUsage_linux.c
src/detection/cursor/cursor_linux.c
src/detection/disk/disk_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gtk.c
src/detection/host/host_linux.c
src/detection/localip/localip_linux.c
src/detection/media/media_linux.c
src/detection/memory/memory_linux.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_linux.c
src/detection/qt.c
src/detection/swap/swap_linux.c
src/detection/temps/temps_linux.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/uptime/uptime_linux.c
src/detection/users/users_linux.c
src/detection/wifi/wifi_linux.c
src/detection/wmtheme/wmtheme_linux.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_nosupport.c
src/detection/bios/bios_nosupport.c
src/detection/board/board_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_linux.c
src/detection/cursor/cursor_nosupport.c
src/detection/cpuUsage/cpuUsage_linux.c
src/detection/disk/disk_linux.c
src/detection/displayserver/displayserver_nosupport.c
src/detection/font/font_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/host/host_android.c
src/detection/localip/localip_linux.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_linux.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_android.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_linux.c
src/detection/swap/swap_linux.c
src/detection/temps/temps_linux.c
src/detection/terminalfont/terminalfont_android.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/uptime/uptime_linux.c
src/detection/users/users_linux.c
src/detection/wifi/wifi_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c
)
elseif(BSD)
list(APPEND LIBFASTFETCH_SRC
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_nosupport.c
src/detection/bios/bios_bsd.c
src/detection/board/board_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_bsd.c
src/detection/cpuUsage/cpuUsage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/disk/disk_bsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gtk.c
src/detection/host/host_bsd.c
src/detection/localip/localip_linux.c
src/detection/media/media_linux.c
src/detection/memory/memory_bsd.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_bsd.c
src/detection/qt.c
src/detection/swap/swap_bsd.c
src/detection/temps/temps_linux.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wifi/wifi_nosupport.c
src/detection/wmtheme/wmtheme_linux.c
)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_apple.c
src/detection/bios/bios_apple.c
src/detection/board/board_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_apple.c
src/detection/cpuUsage/cpuUsage_apple.c
src/detection/cursor/cursor_nosupport.c
src/detection/disk/disk_apple.m
src/detection/disk/disk_bsd.c
src/detection/displayserver/displayserver_apple.c
src/detection/font/font_apple.m
src/detection/gpu/gpu_apple.c
src/detection/host/host_apple.c
src/detection/localip/localip_linux.c
src/detection/media/media_apple.m
src/detection/memory/memory_apple.c
src/detection/opengl/opengl_apple.c
src/detection/os/os_apple.m
src/detection/packages/packages_apple.c
src/detection/poweradapter/poweradapter_apple.c
src/detection/processes/processes_bsd.c
src/detection/swap/swap_apple.c
src/detection/temps/temps_apple.c
src/detection/terminalfont/terminalfont_apple.m
src/detection/terminalshell/terminalshell_linux.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wifi/wifi_apple.m
src/detection/wmtheme/wmtheme_apple.m
src/util/apple/cf_helpers.c
src/util/apple/osascript.m
)
elseif(WIN32)
list(APPEND LIBFASTFETCH_SRC
src/common/networking_windows.c
src/common/processing_windows.c
src/detection/battery/battery_windows.c
src/detection/bios/bios_windows.c
src/detection/board/board_windows.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_windows.c
src/detection/cpuUsage/cpuUsage_windows.c
src/detection/cursor/cursor_windows.c
src/detection/disk/disk_windows.c
src/detection/displayserver/displayserver_windows.c
src/detection/font/font_windows.c
src/detection/gpu/gpu_windows.cpp
src/detection/host/host_windows.c
src/detection/localip/localip_windows.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_windows.c
src/detection/opengl/opengl_windows.c
src/detection/os/os_windows.cpp
src/detection/packages/packages_windows.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_windows.cpp
src/detection/swap/swap_windows.cpp
src/detection/terminalfont/terminalfont_windows.c
src/detection/terminalshell/terminalshell_windows.cpp
src/detection/uptime/uptime_windows.c
src/detection/users/users_windows.c
src/detection/wifi/wifi_windows.c
src/detection/wmtheme/wmtheme_windows.c
src/util/windows/getline.c
src/util/windows/pwd.c
src/util/windows/registry.c
src/util/windows/unicode.c
src/util/windows/utsname.c
src/util/windows/wmi.cpp
)
endif()
add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX_H)
if(HAVE_UTMPX_H)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX_H)
endif()
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
if(NOT ENABLE_${VARNAME})
return()
endif()
if(PKG_CONFIG_FOUND)
pkg_search_module(${VARNAME} QUIET ${PKGCONFIG_NAMES})
endif()
if(NOT ${VARNAME}_FOUND)
find_package(${CMAKE_NAME} QUIET)
set(${VARNAME}_FOUND ${${CMAKE_NAME}_FOUND})
set(${VARNAME}_INCLUDE_DIRS ${${CMAKE_NAME}_INCLUDE_DIRS})
set(${VARNAME}_LIBRARIES ${${CMAKE_NAME}_LIBRARIES})
set(${VARNAME}_CFLAGS_OTHER ${${CMAKE_NAME}_CFLAGS_OTHER})
endif()
if(NOT ${VARNAME}_FOUND)
message(STATUS "Library: missing: ${VARNAME}")
return()
endif()
message(STATUS "Library: found ${VARNAME}")
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
foreach(FLAG ${${VARNAME}_CFLAGS_OTHER})
if(FLAG MATCHES "-D.*")
string(SUBSTRING ${FLAG} 2 -1 FLAG)
target_compile_definitions(libfastfetch PRIVATE ${FLAG})
endif()
endforeach()
endfunction()
ff_lib_enable(LIBPCI
"libpci"
"Pci"
)
ff_lib_enable(VULKAN
"vulkan"
"Vulkan"
)
ff_lib_enable(WAYLAND
"wayland-client"
"WaylandClient"
)
ff_lib_enable(XCB_RANDR
"xcb-randr"
"XcbRandr"
)
ff_lib_enable(XCB
"xcb"
"Xcb"
)
ff_lib_enable(XRANDR
"xrandr"
"XRandr"
)
ff_lib_enable(X11
"x11"
"X11"
)
ff_lib_enable(GIO
"gio-2.0"
"GIO"
)
ff_lib_enable(DCONF
"dconf"
"DConf"
)
ff_lib_enable(DBUS
"dbus-1"
"DBus"
)
ff_lib_enable(XFCONF
"libxfconf-0"
"XFConf"
)
ff_lib_enable(SQLITE3
"sqlite3"
"SQLite3"
)
ff_lib_enable(RPM
"rpm"
"RPM"
)
ff_lib_enable(IMAGEMAGICK7
"MagickCore-7.Q16HDRI;MagickCore-7.Q16;MagickCore-7;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.pc"
"ImageMagick7"
)
ff_lib_enable(IMAGEMAGICK6
"MagickCore-6.Q16HDRI;MagickCore-6.Q16;MagickCore-6;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.pc"
"ImageMagick6"
)
ff_lib_enable(ZLIB
"zlib"
"ZLIB"
)
ff_lib_enable(CHAFA
"chafa>=1.10"
"Chafa"
)
ff_lib_enable(EGL
"egl"
"EGL"
)
ff_lib_enable(GLX
"glx"
"GLX"
)
ff_lib_enable(OSMESA
"osmesa"
"OSMesa"
)
ff_lib_enable(OPENCL
"OpenCL"
"OpenCL"
)
ff_lib_enable(LIBCJSON
"libcjson"
"CJson"
)
ff_lib_enable(FREETYPE
"freetype2"
"FreeType2"
)
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
target_link_libraries(libfastfetch PRIVATE Threads::Threads)
endif()
endif()
if(ENABLE_BUFFER)
target_compile_definitions(libfastfetch PRIVATE FF_ENABLE_BUFFER)
endif()
if(APPLE)
target_link_libraries(libfastfetch
PRIVATE "-framework CoreFoundation"
PRIVATE "-framework IOKit"
PRIVATE "-framework OpenGL"
PRIVATE "-framework OpenCL"
PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreWLAN"
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
)
elseif(WIN32)
target_link_libraries(libfastfetch
PRIVATE "dwmapi"
PRIVATE "gdi32"
PRIVATE "iphlpapi"
PRIVATE "ole32"
PRIVATE "oleaut32"
PRIVATE "opengl32"
PRIVATE "wbemuuid"
PRIVATE "ws2_32"
PRIVATE "ntdll"
PRIVATE "version"
PRIVATE "setupapi"
PRIVATE "dxgi"
PRIVATE "wtsapi32"
PRIVATE "powrprof"
)
if(USE_WIN_NTAPI)
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI)
endif()
if(USE_WIN_GPU_DXGI)
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_GPU_DXGI)
endif()
endif()
target_include_directories(libfastfetch
PUBLIC ${PROJECT_BINARY_DIR}
PUBLIC ${PROJECT_SOURCE_DIR}/src
)
target_link_libraries(libfastfetch
PRIVATE ${CMAKE_DL_LIBS}
)
######################
# Executable targets #
######################
add_executable(fastfetch
src/fastfetch.c
)
target_compile_definitions(fastfetch
PRIVATE FASTFETCH_TARGET_BINARY_NAME=fastfetch
)
target_link_libraries(fastfetch
PRIVATE libfastfetch
)
add_executable(flashfetch
src/flashfetch.c
)
target_compile_definitions(flashfetch
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
)
target_link_libraries(flashfetch
PRIVATE libfastfetch
)
if(WIN32)
set(TARGET_NAME fastfetch)
target_sources(fastfetch
PRIVATE src/util/windows/version.rc
)
set(TARGET_NAME flashfetch)
target_sources(flashfetch
PRIVATE src/util/windows/version.rc
)
endif()
###################
# Testing targets #
###################
if (BUILD_TESTS)
add_executable(fastfetch-test-strbuf
tests/strbuf.c
)
target_link_libraries(fastfetch-test-strbuf
PRIVATE libfastfetch
)
add_executable(fastfetch-test-list
tests/list.c
)
target_link_libraries(fastfetch-test-list
PRIVATE libfastfetch
)
enable_testing()
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
add_test(NAME test-list COMMAND fastfetch-test-list)
endif()
##################
# install target #
##################
include(GNUInstallDirs)
install(
TARGETS fastfetch flashfetch
DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
install(
FILES "${CMAKE_SOURCE_DIR}/src/data/config_system.txt"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/${CMAKE_PROJECT_NAME}"
RENAME "config.conf"
)
install(
FILES "${CMAKE_SOURCE_DIR}/completions/bash"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions"
RENAME "${CMAKE_PROJECT_NAME}"
)
install(
DIRECTORY "${CMAKE_SOURCE_DIR}/presets"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}"
)
install(
FILES "${CMAKE_SOURCE_DIR}/LICENSE"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}"
)
##################
# package target #
##################
set(CPACK_GENERATOR "TGZ;ZIP")
if(LINUX)
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
endif()
set(CPACK_SET_DESTDIR ON)
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
set(CPACK_PACKAGE_DESCRIPTION "\
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
It is written in c to achieve much better performance.\
")
include(CPack)
-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 methode 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
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Linus Dierheimer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+16 -147
View File
@@ -1,160 +1,29 @@
# Fastfetch
# Fastfetch Benchmark Data
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
This branch stores continuous performance benchmark data for Fastfetch on Linux, macOS, and Windows.
<img src="screenshots/example1.png" width="49%" align="left" />
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
<img src="screenshots/example4.png" width="49%" align="left" />
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
<img src="screenshots/example2.png" width="48%" align="top" />
<img src="screenshots/example3.png" width="48%" align="top" />
<img src="screenshots/example5.png" height="15%" align="top" />
The data is generated and updated automatically by GitHub Actions. Please do not edit generated benchmark files manually.
## Customization
## Benchmark Dashboard
With customization and speed being two competing goals, this project actually builds two executables.
The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `~/.config/fastfetch/config.conf`. To view the available options run `fastfetch --help`.
The second executable being built is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
At the moment the performance difference is measurable, but too small to be human recognizable. But the leap will get bigger with more and more options coming, and on slow machines this might actually make a difference.
<https://fastfetch-cli.github.io/fastfetch/dev/bench/>
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
## Metrics
## Dependencies
The benchmark data includes:
Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions.
- Execution time for each Fastfetch module, measured in milliseconds;
- Total Fastfetch process execution time, measured in milliseconds.
All metrics use the “smaller is better” comparison mode.
The following libraries are used if present at runtime:
## Update Workflow
### Linux and FreeBSD
Benchmark data is generated from the `dev` branch CI workflow and updated after all platform build jobs have completed.
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
* [`libxcb-randr`](https://xcb.freedesktop.org/),
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
[`libxcb`](https://xcb.freedesktop.org/),
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
* [`libEGL`](https://www.khronos.org/registry/EGL/),
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
Related workflow files:
### macOS
- `.github/workflows/build-benchmark.yml`
- `.github/workflows/ci.yml`
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
### Windows
* [`wlanapi`](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/): A system dll which isn't supported by Windows Server by default. Used for Wifi info detection.
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Used for Windows Terminal font detection. [`cjson`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-cjson)
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers)
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd)
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, special build `fastfetch-windows-old` in [Github Actions](https://github.com/LinusDierheimer/fastfetch/actions) is provided to support these old systems, which
1. Build with the ancient MSVCRT C runtime library, instead of the modern [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library
2. Disable stdout application buffer, which seems to problematic for ConEmu.
For the image logo, only chafa is supported due to [the design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not built by default due to the massive dependencies of imagemagick. You must built it yourself.
### Android
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
## Support status
All categories not listed here should work without needing a specific implementation.
##### Available Modules
```
Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom
```
##### Logos
```
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin
```
* Most of the logos have a small variant. Access it by appending _small to the logo name.
* Some logos have an old variant. Access it by appending _old to the logo name.
* To disable the logo, use `--logo none`.
* Get a list of all available logos with `fastfetch --print-logos`.
* Printing images as logo is supported using Sixel / Kitty / iTerm graphics protocol or chafas image to text conversion.
##### Package managers
```
Pacman, dpkg, rpm, emerge, eopkg, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop, Chocolatey
```
##### WM themes
```
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), DWM (Windows)
```
##### DE versions
```
KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
```
##### Terminal fonts
```
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, Kitty, LXTerminal, Deepin Terminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu
```
## Building
fastfetch uses [`cmake`](https://cmake.org/) for building. [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is recommended for better library detection. The simplest steps to build the fastfetch and flashfetch binaries are:
```bash
mkdir -p build
cd build
cmake ..
cmake --build . --target fastfetch --target flashfetch
```
If the build process fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
### Building on Windows
Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested.
1. Install [MSYS2](https://www.msys2.org/#installation)
1. Open `MSYS2 CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
1. Install dependencies
```bash
pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
```
1. Follow building instructions of Linux
## Packaging
### Repositories
[![Packaging status](https://repology.org/badge/vertical-allrepos/fastfetch.svg?header=)](https://repology.org/project/fastfetch/versions)
### Manual
* DEB / RPM package: `cmake --build . --target package`
* Install directly: `cmake --install . --prefix /usr/local`
## FAQ
Q: Why do you need a very performant version of neofetch?
> I like putting neofetch in my ~/.bashrc to have a system overwiew whenever I use the terminal, but the slow speed annoyed me, so I created this. Also neofetch didn't output everything correctly (e.g Font is displayed as "[Plasma], Noto Sans, 10 [GTK2/3]") and writing my own tool gave me the possibility to fine tune it to run perfectly on at least my configuration.
Q: It does not display [*] correctly for me, what can I do?
> This is most likely because your system is not implemented (yet). At the moment I am focusing more on making the core app better, than adding more configurations. Feel free to open a pull request if you want to add support for your configuration
Commit information and dates are recorded automatically by the Continuous Benchmark Action.
-414
View File
@@ -1,414 +0,0 @@
#!/usr/bin/env bash
__fastfetch_complete_help()
{
local __ff_helps=(
"color"
"format"
"load-config"
"os-format"
"host-format"
"kernel-format"
"uptime-format"
"processes-format"
"packages-format"
"shell-format"
"resolution-format"
"de-format"
"wm-format"
"wm-theme-format"
"theme-format"
"icons-format"
"font-format"
"cursor-format"
"terminal-format"
"terminal-font-format"
"cpu-format"
"cpu-usage-format"
"gpu-format"
"memory-format"
"swap-format"
"disk-format"
"battery-format"
"poweradapter-format"
"locale-format"
"local-ip-format"
"public-ip-format"
"player-format"
"media-format"
"datetime-format"
"date-format"
"time-format"
"vulkan-format"
"opengl-format"
"opencl-format"
)
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
}
__fastfetch_complete_bool()
{
COMPREPLY=($(compgen -W "true false" -- "$CURRENT_WORD"))
}
__fastfetch_complete_string()
{
if [[ $CURRENT_WORD != "" ]]; then
COMPREPLY=("$CURRENT_WORD")
fi
}
__fastfetch_complete_path()
{
COMPREPLY=($(compgen -A file -- "$CURRENT_WORD"))
}
__fastfetch_complete_logo()
{
COMPREPLY=($(compgen -W "$(fastfetch --list-logos-autocompletion)" -- "$CURRENT_WORD"))
}
__fastfetch_complete_logo_type()
{
local __ff_logo_types=(
"auto"
"builtin"
"file"
"raw"
"sixel"
"kitty"
"chafa"
)
COMPREPLY=($(compgen -W "${__ff_logo_types[*]}" -- "$CURRENT_WORD"))
}
__fastfetch_complete_binary_prefix()
{
local __ff_binary_prefixes=(
"iec"
"si"
"jedec"
)
COMPREPLY=($(compgen -W "${__ff_binary_prefixes[*]}" -- "$CURRENT_WORD"))
}
__fastfetch_complete_gl()
{
local __ff_gl_types=(
"auto"
"egl"
"glx"
"osmesa"
)
COMPREPLY=($(compgen -W "${__ff_gl_types[*]}" -- "$CURRENT_WORD"))
}
__fastfetch_complete_option()
{
local FF_OPTIONS_ALL=(
"${FF_OPTIONS_BOOL[@]}"
"${FF_OPTIONS_STRING[@]}"
"${FF_OPTIONS_PATH[@]}"
"${FF_OPTIONS_LOGO[@]}"
"${FF_OPTIONS_LOGO_TYPE[@]}"
"${FF_OPTIONS_BINARY_PREFIX[@]}"
"${FF_OPTIONS_GL[@]}"
)
if [[ $WORD_COUND -lt 3 ]]; then
FF_OPTIONS_ALL+=(
"${FF_OPTIONS_SINGLE[@]}"
"${FF_OPTIONS_HELP[@]}"
)
fi
for ff_word in ${COMP_WORDS[@]}; do
if [[ $ff_word == $CURRENT_WORD ]]; then
break
fi
FF_OPTIONS_ALL=("${FF_OPTIONS_ALL[@]/$ff_word}")
done
COMPREPLY=($(compgen -W "${FF_OPTIONS_ALL[*]}" -- "$CURRENT_WORD"))
}
__fastfetch_previous_matches()
{
for ff_option in "$@"; do
if [[ $ff_option == "$PREVIOUS_WORD" ]]; then
return 0
fi
done
return 1
}
__fastfetch_completion()
{
local CURRENT_WORD="${COMP_WORDS[$COMP_CWORD]}"
local PREVIOUS_WORD="${COMP_WORDS[$COMP_CWORD - 1]}"
local WORD_COUND="${#COMP_WORDS[@]}"
local FF_OPTIONS_SINGLE=(
"-v"
"--version"
"--list-logos"
"--list-modules"
"--list-presets"
"--list-features"
"--print-logos"
"--print-config-system"
"--print-config-user"
"--print-structure"
)
local FF_OPTIONS_HELP=(
"-h"
"--help"
)
local FF_OPTIONS_BOOL=(
"-r"
"--show-errors"
"--logo-print-remaining"
"--multithreading"
"--stat"
"--allow-slow-operations"
"--disable-linewrap"
"--hide-cursor"
"--cpu-temp"
"--gpu-temp"
"--battery-temp"
"--localip-show-ipv4"
"--localip-show-ipv6"
"--localip-show-loop"
"--localip-name-prefix"
"--escape-bedrock"
"--pipe"
"--title-fqdn"
"--escape-bedrock"
"--disk-show-removable"
"--disk-show-hidden"
)
local FF_OPTIONS_STRING=(
"--logo-type"
"--logo-padding"
"--logo-padding-left"
"--logo-padding-right"
"--logo-color-1"
"--logo-color-2"
"--logo-color-3"
"--logo-color-4"
"--logo-color-5"
"--logo-color-6"
"--logo-color-7"
"--logo-color-8"
"--logo-width"
"--logo-height"
"--logo-color-9"
"-c"
"--color"
"--color-keys"
"--color-title"
"--separator"
"-s"
"--structure"
"--set"
"--set-keyless"
"--player-name"
"--percent-type"
"--public-ip-url"
"--public-ip-timeout"
"--weather-output-format"
"--weather-timeout"
"--os-key"
"--os-format"
"--os-error"
"--host-key"
"--host-format"
"--host-error"
"--kernel-key"
"--kernel-format"
"--kernel-error"
"--uptime-key"
"--uptime-format"
"--uptime-error"
"--processes-key"
"--processes-format"
"--processes-error"
"--packages-key"
"--packages-format"
"--packages-error"
"--shell-key"
"--shell-format"
"--shell-error"
"--resolution-key"
"--resolution-format"
"--resolution-error"
"--de-key"
"--de-format"
"--de-error"
"--wm-key"
"--wm-format"
"--wm-error"
"--wm-theme-key"
"--wm-theme-format"
"--wm-theme-error"
"--theme-key"
"--theme-format"
"--theme-error"
"--icons-key"
"--icons-format"
"--icons-error"
"--font-key"
"--font-format"
"--font-error"
"--cursor-key"
"--cursor-format"
"--cursor-error"
"--terminal-key"
"--terminal-format"
"--terminal-error"
"--terminal-font-key"
"--terminal-font-format"
"--terminal-font-error"
"--cpu-key"
"--cpu-format"
"--cpu-error"
"--cpu-useage-key"
"--cpu-useage-format"
"--cpu-useage-error"
"--gpu-key"
"--gpu-format"
"--gpu-error"
"--memory-key"
"--memory-format"
"--memory-error"
"--swap-key"
"--swap-format"
"--swap-error"
"--disk-key"
"--disk-format"
"--disk-error"
"--battery-key"
"--battery-format"
"--battery-error"
"--poweradapter-key"
"--poweradapter-format"
"--poweradapter-error"
"--locale-key"
"--locale-format"
"--locale-error"
"--local-ip-key"
"--local-ip-format"
"--local-ip-error"
"--public-ip-key"
"--public-ip-format"
"--public-ip-error"
"--wifi-key"
"--wifi-format"
"--wifi-error"
"--weather-key"
"--weather-format"
"--weather-error"
"--player-key"
"--player-format"
"--player-error"
"--media-key"
"--media-format"
"--media-error"
"--datetime-key"
"--datetime-format"
"--datetime-error"
"--date-key"
"--date-format"
"--date-error"
"--time-key"
"--time-format"
"--time-error"
"--vulkan-key"
"--vulkan-format"
"--vulkan-error"
"--opengl-key"
"--opengl-format"
"--opengl-error"
"--opencl-key"
"--opencl-format"
"--opencl-error"
"--users-key"
"--users-format"
"--users-error"
)
local FF_OPTIONS_PATH=(
"--load-config"
"--os-file"
"--lib-pci"
"--lib-vulkan"
"--lib-wayland"
"--lib-xcb-randr"
"--lib-xcb"
"--lib-xrandr"
"--lib-X11"
"--lib-gio"
"--lib-dconf"
"--lib-dbus"
"--lib-xfconf"
"--lib-sqlite3"
"--lib-rpm"
"--lib-imagemagick"
"--lib-z"
"--lib-chafa"
"--lib-egl"
"--lib-glx"
"--lib-osmesa"
"--lib-opencl"
"--battery-dir"
)
local FF_OPTIONS_LOGO=(
"-l"
"--logo"
)
local FF_OPTIONS_LOGO_TYPE=(
"--logo-type"
)
local FF_OPTIONS_BINARY_PREFIX=(
"--binary-prefix"
)
local FF_OPTIONS_GL=(
"--gl"
)
if __fastfetch_previous_matches "${FF_OPTIONS_SINGLE[@]}"; then
return
elif [[ $WORD_COUND -gt 3 && ( ${COMP_WORDS[$COMP_CWORD - 2]} == "--help" || ${COMP_WORDS[$COMP_CWORD - 2]} == "-h" ) ]]; then
return
elif [[ $CURRENT_WORD == "-"* ]]; then
__fastfetch_complete_option
elif __fastfetch_previous_matches "${FF_OPTIONS_HELP[@]}"; then
__fastfetch_complete_help
elif __fastfetch_previous_matches "${FF_OPTIONS_BOOL[@]}"; then
__fastfetch_complete_bool
elif __fastfetch_previous_matches "${FF_OPTIONS_STRING[@]}"; then
__fastfetch_complete_string
elif __fastfetch_previous_matches "${FF_OPTIONS_PATH[@]}"; then
__fastfetch_complete_path
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO[@]}"; then
__fastfetch_complete_logo
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO_TYPE[@]}"; then
__fastfetch_complete_logo_type
elif __fastfetch_previous_matches "${FF_OPTIONS_BINARY_PREFIX[@]}"; then
__fastfetch_complete_binary_prefix
elif __fastfetch_previous_matches "${FF_OPTIONS_GL[@]}"; then
__fastfetch_complete_gl
else
__fastfetch_complete_option
fi
}
complete -F __fastfetch_completion fastfetch
+228260
View File
File diff suppressed because it is too large Load Diff
+424
View File
@@ -0,0 +1,424 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fastfetch · Benchmark</title>
<style>
:root {
color-scheme: light;
--page: #f5f7fb;
--card: #fff;
--text: #172033;
--muted: #64748b;
--border: #dbe3ef;
--accent: #2563eb;
--accent-soft: #dbeafe;
--chart-text: #334155;
--chart-grid: #cbd5e1;
}
:root[data-theme="dark"] {
color-scheme: dark;
--page: #0f172a; --card: #172033; --text: #e5edf8; --muted: #9aabc1; --border: #334155; --accent-soft: #1e3a8a;
--chart-text: #f1f5f9;
--chart-grid: #475569;
}
* { box-sizing: border-box; }
body { max-width: 1440px; margin: 0 auto; padding: 2.5rem 1.25rem 4rem; background: var(--page); color: var(--text); font: 16px/1.5 system-ui, -apple-system, sans-serif; }
header { margin-bottom: 1.75rem; }
.header-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
h1 { margin: 0; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: -.04em; }
h2 { margin: 0; font-size: 1.25rem; }
p { color: var(--muted); }
.intro { margin: .6rem 0 1rem; }
.links a { color: var(--accent); font-weight: 600; text-decoration: none; }
.links a:hover { text-decoration: underline; }
.theme-toggle, .fullscreen { border: 1px solid var(--border); border-radius: .55rem; padding: .5rem .8rem; background: var(--card); color: var(--text); cursor: pointer; font: inherit; font-weight: 600; }
.theme-toggle:hover, .fullscreen:hover { border-color: var(--accent); color: var(--accent); }
.tabs { display: flex; flex-wrap: wrap; gap: .6rem; margin: 1.5rem 0; padding: .35rem; border: 1px solid var(--border); border-radius: .8rem; background: var(--card); }
.tab { border: 0; border-radius: .55rem; padding: .65rem 1.15rem; background: transparent; color: var(--muted); cursor: pointer; font: inherit; font-weight: 700; }
.tab:hover, .tab[aria-selected="true"] { background: var(--accent); color: #fff; }
.tab-panel[hidden] { display: none; }
.platform-title { display: flex; align-items: center; gap: .65rem; margin: 1.5rem 0 1rem; }
.platform-title::before { content: ''; width: .35rem; height: 1.4rem; border-radius: 1rem; background: var(--accent); }
.charts { display: flex; flex-direction: column; gap: 1.25rem; }
.chart { min-width: 0; padding: 1.25rem; border: 1px solid var(--border); border-radius: 1rem; background: var(--card); box-shadow: 0 8px 28px #0f172a0c; }
.chart:fullscreen { overflow: auto; padding: 2rem; background: var(--page); }
.chart:fullscreen .canvas-wrap { height: calc(100vh - 13rem); }
.chart-header { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .75rem; }
.chart-header span { color: var(--muted); font-size: .85rem; }
.canvas-wrap { position: relative; height: 360px; }
.chart-actions { display: flex; align-items: center; gap: .75rem; }
.legend-actions { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: 1rem; }
.legend-action { border: 1px solid var(--border); border-radius: .45rem; padding: .35rem .6rem; background: var(--card); color: var(--muted); cursor: pointer; font: inherit; font-size: .8rem; }
.legend-action:hover { border-color: var(--accent); color: var(--accent); }
.legend { display: flex; flex-wrap: wrap; gap: .35rem .9rem; margin-top: 1rem; }
.legend-item { display: inline-flex; align-items: center; gap: .4rem; border: 0; padding: .15rem 0; background: transparent; color: var(--text); cursor: pointer; font: inherit; font-size: .85rem; }
.legend-item.is-hidden { color: var(--muted); }
.legend-swatch { width: .75rem; height: .75rem; border-radius: 50%; }
.legend-item.is-hidden .legend-swatch { opacity: .35; }
.chart-tooltip { position: fixed; z-index: 1000; pointer-events: none; width: min(90vw, 900px); max-height: calc(100vh - 24px); overflow: hidden; padding: .7rem .85rem; border: 1px solid var(--border); border-radius: .6rem; background: var(--card); color: var(--text); box-shadow: 0 10px 30px #0f172a33; font-size: .8rem; opacity: 0; transition: opacity .1s ease; }
.chart-tooltip-title { margin-bottom: .35rem; font-weight: 700; white-space: normal; overflow-wrap: anywhere; }
.chart-tooltip-message { margin-bottom: .35rem; color: var(--muted); font-weight: 400; white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.chart-tooltip-body { max-height: calc(100vh - 76px); overflow: auto; columns: 220px auto; column-gap: 1.5rem; }
.chart-tooltip-row { display: flex; align-items: center; gap: .45rem; break-inside: avoid; white-space: nowrap; }
.chart-tooltip-swatch { width: .55rem; height: .55rem; border-radius: 50%; flex: 0 0 auto; }
.empty { padding: 2rem 0; color: var(--muted); }
</style>
<script src="data.js"></script>
<script src="https://unpkg.com/chart.js@latest/dist/chart.umd.min.js"></script>
</head>
<body>
<header>
<div class="header-row">
<h1>Fastfetch Benchmark</h1>
<button id="theme-toggle" class="theme-toggle" type="button"></button>
</div>
<p class="intro">Performance history grouped by CPU family. Each chart contains all modules and the total process time for one operating system and architecture. All metric series are shown by default except total process time, module Weather, and module PublicIp — toggle any series from the legend below the chart.</p>
<p class="links"><a href="data.js">Download raw benchmark data</a></p>
</header>
<nav id="tabs" class="tabs" aria-label="CPU architecture"></nav>
<main id="panels"><p class="empty">Loading charts…</p></main>
<script>
(() => {
const benchmarkData = window.BENCHMARK_DATA || {};
const entries = Object.values(benchmarkData.entries || {}).flat();
const groups = new Map();
function architectureFamily(arch) {
const normalized = arch.toLowerCase();
if (/^(amd64|x86_64|x86|i[3-6]86)$/.test(normalized)) return 'Intel';
if (/^(aarch64|arm64|armv[5-8].*|arm)$/.test(normalized)) return 'ARM';
return 'Other';
}
function parseName(name) {
let match = name.match(/^fastfetch (linux|macos|windows) ([^ ]+) (module .+|total process time)$/i);
if (match) {
return { platform: match[1].toLowerCase(), arch: match[2], metric: match[3] };
}
// Keep older macOS records visible while new records use the platform field.
match = name.match(/^fastfetch ([^ ]+) (module .+|total process time)$/i);
return match ? { platform: 'macos', arch: match[1], metric: match[2] } : null;
}
function entryMetadata(entry) {
const raw = entry.commit?.timestamp ?? entry.date;
const date = new Date(raw);
return {
date: Number.isNaN(date.valueOf()) ? String(entry.date ?? '') : date.toISOString(),
sha: entry.commit?.id ?? 'unknown',
message: entry.commit?.message?.trim() ?? ''
};
}
for (const entry of entries) {
const metricsByGroup = new Map();
for (const bench of entry.benches || []) {
const parsed = parseName(bench.name);
if (!parsed) continue;
const key = `${parsed.platform} ${parsed.arch}`;
if (!metricsByGroup.has(key)) metricsByGroup.set(key, new Map());
metricsByGroup.get(key).set(parsed.metric, bench.value);
}
for (const [key, metrics] of metricsByGroup) {
if (!groups.has(key)) groups.set(key, []);
groups.get(key).push({ ...entryMetadata(entry), metrics });
}
}
const colors = [
'#2563eb', '#dc2626', '#16a34a', '#9333ea', '#ea580c', '#0891b2',
'#db2777', '#65a30d', '#4f46e5', '#ca8a04', '#0f766e', '#be123c'
];
// Series hidden on first render; every other metric is shown by default.
const hiddenByDefault = new Set(['total process time', 'module Weather', 'module PublicIp']);
const tabs = document.getElementById('tabs');
const panels = document.getElementById('panels');
const root = document.documentElement;
const themeToggle = document.getElementById('theme-toggle');
const savedTheme = localStorage.getItem('fastfetch-benchmark-theme');
let theme = savedTheme || (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
const chartsByInstance = [];
if (!window.Chart) {
tabs.hidden = true;
panels.innerHTML = '<p class="empty">Failed to load Chart.js.</p>';
return;
}
panels.replaceChildren();
function chartColors() {
const styles = getComputedStyle(root);
return {
text: styles.getPropertyValue('--chart-text').trim(),
grid: styles.getPropertyValue('--chart-grid').trim()
};
}
function externalTooltipHandler(context) {
const { chart, tooltip } = context;
let tooltipElement = chart.canvas.parentNode.querySelector('.chart-tooltip');
if (!tooltipElement) {
tooltipElement = document.createElement('div');
tooltipElement.className = 'chart-tooltip';
chart.canvas.parentNode.appendChild(tooltipElement);
}
if (tooltip.opacity === 0) {
tooltipElement.style.opacity = '0';
return;
}
tooltipElement.replaceChildren();
const title = document.createElement('div');
title.className = 'chart-tooltip-title';
const row = chart._benchmarkRows[tooltip.dataPoints[0].dataIndex];
title.textContent = `${new Date(row.date).toLocaleString()} · ${row.sha}`;
tooltipElement.appendChild(title);
if (row.message) {
const message = document.createElement('div');
message.className = 'chart-tooltip-message';
message.textContent = row.message;
tooltipElement.appendChild(message);
}
const bodyElement = document.createElement('div');
bodyElement.className = 'chart-tooltip-body';
for (const body of [...tooltip.dataPoints].sort((a, b) => b.parsed.y - a.parsed.y)) {
const item = document.createElement('div');
item.className = 'chart-tooltip-row';
const swatch = document.createElement('span');
swatch.className = 'chart-tooltip-swatch';
swatch.style.background = body.dataset.borderColor;
const value = document.createElement('span');
value.textContent = `${body.dataset.label}: ${body.formattedValue} ms`;
item.append(swatch, value);
bodyElement.appendChild(item);
}
tooltipElement.appendChild(bodyElement);
const canvasRect = chart.canvas.getBoundingClientRect();
const margin = 12;
let left = canvasRect.left + tooltip.caretX + margin;
let top = canvasRect.top + tooltip.caretY + margin;
tooltipElement.style.left = `${left}px`;
tooltipElement.style.top = `${top}px`;
tooltipElement.style.opacity = '0';
const tooltipRect = tooltipElement.getBoundingClientRect();
if (left + tooltipRect.width > window.innerWidth - margin) left = canvasRect.left + tooltip.caretX - tooltipRect.width - margin;
if (top + tooltipRect.height > window.innerHeight - margin) top = canvasRect.top + tooltip.caretY - tooltipRect.height - margin;
tooltipElement.style.left = `${Math.max(margin, left)}px`;
tooltipElement.style.top = `${Math.max(margin, top)}px`;
tooltipElement.style.opacity = '1';
}
function updateTheme() {
root.dataset.theme = theme;
themeToggle.textContent = theme === 'dark' ? '☀ Light mode' : '☾ Dark mode';
themeToggle.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`);
const colors = chartColors();
Chart.defaults.color = colors.text;
Chart.defaults.borderColor = colors.grid;
for (const chart of chartsByInstance) {
chart.options.scales.x.title.color = colors.text;
chart.options.scales.x.ticks.color = colors.text;
chart.options.scales.x.grid.color = colors.grid;
chart.options.scales.y.title.color = colors.text;
chart.options.scales.y.ticks.color = colors.text;
chart.options.scales.y.grid.color = colors.grid;
chart.update();
}
}
themeToggle.addEventListener('click', () => {
theme = theme === 'dark' ? 'light' : 'dark';
localStorage.setItem('fastfetch-benchmark-theme', theme);
updateTheme();
});
updateTheme();
const families = new Map();
for (const [key, rows] of groups) {
const arch = key.slice(key.lastIndexOf(' ') + 1);
const family = architectureFamily(arch);
if (!families.has(family)) families.set(family, []);
families.get(family).push({ key, rows });
}
// 'Other' is intentionally not rendered: it only catches stray series (e.g. the retired
// 'macos universal' records) that should not show up as their own tab
const familyOrder = ['Intel', 'ARM'];
const availableFamilies = familyOrder.filter(family => families.has(family));
for (const [index, family] of availableFamilies.entries()) {
const tab = document.createElement('button');
const panelId = `panel-${family.toLowerCase()}`;
tab.className = 'tab';
tab.type = 'button';
tab.id = `tab-${family.toLowerCase()}`;
tab.setAttribute('role', 'tab');
tab.textContent = family;
tab.setAttribute('aria-controls', panelId);
tab.setAttribute('aria-selected', index === 0 ? 'true' : 'false');
tabs.appendChild(tab);
const panel = document.createElement('section');
panel.className = 'tab-panel';
panel.id = panelId;
panel.setAttribute('role', 'tabpanel');
panel.hidden = index !== 0;
panel.setAttribute('aria-labelledby', tab.id);
const title = document.createElement('h2');
title.className = 'platform-title';
title.textContent = `${family} processors`;
panel.appendChild(title);
const chartGrid = document.createElement('div');
chartGrid.className = 'charts';
panel.appendChild(chartGrid);
panels.appendChild(panel);
tab.addEventListener('click', () => {
for (const otherTab of tabs.children) otherTab.setAttribute('aria-selected', otherTab === tab ? 'true' : 'false');
for (const otherPanel of panels.children) otherPanel.hidden = otherPanel !== panel;
});
for (const { key, rows } of families.get(family).sort((a, b) => a.key.localeCompare(b.key))) {
rows.sort((a, b) => a.date.localeCompare(b.date));
const metrics = [...new Set(rows.flatMap(row => [...row.metrics.keys()]))].sort((a, b) => {
if (a === 'total process time') return -1;
if (b === 'total process time') return 1;
return a.localeCompare(b);
});
const section = document.createElement('article');
section.className = 'chart';
const chartHeader = document.createElement('div');
chartHeader.className = 'chart-header';
const chartTitle = document.createElement('h2');
chartTitle.textContent = key;
const chartActions = document.createElement('div');
chartActions.className = 'chart-actions';
const chartHint = document.createElement('span');
chartHint.textContent = `${rows.length} run${rows.length === 1 ? '' : 's'}`;
const fullscreen = document.createElement('button');
fullscreen.className = 'fullscreen';
fullscreen.type = 'button';
fullscreen.textContent = '⛶ Fullscreen';
fullscreen.addEventListener('click', () => {
if (document.fullscreenElement) document.exitFullscreen();
else section.requestFullscreen();
});
chartActions.append(chartHint, fullscreen);
chartHeader.append(chartTitle, chartActions);
const canvasWrap = document.createElement('div');
canvasWrap.className = 'canvas-wrap';
const canvas = document.createElement('canvas');
canvasWrap.appendChild(canvas);
section.append(chartHeader, canvasWrap);
chartGrid.appendChild(section);
const colorsForChart = chartColors();
const chart = new Chart(canvas, {
type: 'line',
data: {
labels: rows.map(row => row.sha.slice(0, 7)),
datasets: metrics.map((metric, index) => ({
label: metric,
data: rows.map(row => row.metrics.has(metric) ? row.metrics.get(metric) : null),
borderColor: colors[index % colors.length],
backgroundColor: colors[index % colors.length],
pointRadius: 3,
tension: 0.2,
spanGaps: true,
hidden: hiddenByDefault.has(metric)
}))
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: { mode: 'index', intersect: false },
plugins: {
legend: { display: false },
tooltip: {
enabled: false,
external: externalTooltipHandler,
callbacks: {
title: tooltipItems => {
const row = rows[tooltipItems[0].dataIndex];
return `${row.date} · ${row.sha}`;
}
}
}
},
scales: {
x: { title: { display: true, text: 'Date', color: colorsForChart.text }, ticks: { color: colorsForChart.text }, grid: { color: colorsForChart.grid } },
y: { beginAtZero: true, title: { display: true, text: 'Milliseconds', color: colorsForChart.text }, ticks: { color: colorsForChart.text }, grid: { color: colorsForChart.grid } }
}
}
});
chart._benchmarkRows = rows;
chartsByInstance.push(chart);
const legendActions = document.createElement('div');
legendActions.className = 'legend-actions';
const legend = document.createElement('div');
legend.className = 'legend';
const legendItems = [];
function refreshLegend() {
legendItems.forEach((item, metricIndex) => {
item.classList.toggle('is-hidden', !chart.isDatasetVisible(metricIndex));
});
}
function setAllLegends(visible) {
metrics.forEach((metric, metricIndex) => chart.setDatasetVisibility(metricIndex, visible));
refreshLegend();
chart.update();
}
function addLegendAction(label, action) {
const button = document.createElement('button');
button.className = 'legend-action';
button.type = 'button';
button.textContent = label;
button.addEventListener('click', action);
legendActions.appendChild(button);
}
addLegendAction('Show all', () => setAllLegends(true));
addLegendAction('Toggle all', () => {
metrics.forEach((metric, metricIndex) => chart.setDatasetVisibility(metricIndex, !chart.isDatasetVisible(metricIndex)));
refreshLegend();
chart.update();
});
addLegendAction('Reset', () => {
metrics.forEach((metric, metricIndex) => chart.setDatasetVisibility(metricIndex, !hiddenByDefault.has(metric)));
refreshLegend();
chart.update();
});
metrics.forEach((metric, metricIndex) => {
const item = document.createElement('button');
item.className = `legend-item${chart.isDatasetVisible(metricIndex) ? '' : ' is-hidden'}`;
item.type = 'button';
item.innerHTML = `<span class="legend-swatch" style="background:${colors[metricIndex % colors.length]}"></span>${metric}`;
item.addEventListener('click', () => {
chart.setDatasetVisibility(metricIndex, !chart.isDatasetVisible(metricIndex));
item.classList.toggle('is-hidden', !chart.isDatasetVisible(metricIndex));
chart.update();
});
legendItems.push(item);
legend.appendChild(item);
});
section.append(legendActions, legend);
}
}
if (!availableFamilies.length) {
tabs.hidden = true;
panels.innerHTML = '<p class="empty">No benchmark data available.</p>';
}
})();
</script>
</body>
</html>
-1
View File
@@ -1 +0,0 @@
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors
-3
View File
@@ -1,3 +0,0 @@
--logo arch
--os-format "Arch Linux ({12})"
--packages-format "{} (pacman)"
-3
View File
@@ -1,3 +0,0 @@
--disable-linewrap false
--multithreading false
--show-errors
-3
View File
@@ -1,3 +0,0 @@
--load-config devinfo
--load-config all
--load-config verbose
-1
View File
@@ -1 +0,0 @@
# Load with --load-config examples/1
-24
View File
@@ -1,24 +0,0 @@
# Load with --load-config examples/2
# Note that you must replace the image path to an existing image to display it.
--kitty /home/linus/Bilder/Gentoo.png
--logo-width 28
--separator "  "
--set-keyless HardwareStart=┌───────── \e[1mHardware Information\e[0m ─────────┐
--set-keyless SoftwareStart=├───────── \e[1mSoftware Information\e[0m ─────────┤
--set-keyless InformationEnd=└────────────────────────────────────────┘
--set-keyless Colors= \e[38m \e[37m \e[36m \e[35m \e[34m \e[33m \e[32m \e[31m
--structure HardwareStart:Host:CPU:GPU:SoftwareStart:OS:Kernel:WM:Shell:Terminal:TerminalFont:Packages:InformationEnd:Colors
--host-key " "
--cpu-key " "
--gpu-key " ﬙"
--os-key " "
--kernel-key " "
--wm-key " "
--shell-key " "
--terminal-key " "
--terminal-font-key " "
--packages-key " "
-7
View File
@@ -1,7 +0,0 @@
# Load with --load-config example/3
--logo debian_small
--structure Vulkan:OpenGL:OpenCL:Memory:Disk:LocalIP
--binary-prefix si
--localip-show-loop false
--disk-folders /:/home:/boot:/efi
-7
View File
@@ -1,7 +0,0 @@
# Load with --load-config examples/4
--color blue
--logo arch_small
--logo-padding-right 1
--separator "  "
--structure Date:Time:Break:Player:Media
-11
View File
@@ -1,11 +0,0 @@
# Load with --load-config examples/5
--logo none
--color reset_magenta
--structure Theme:Icons:Font:Cursor
--theme-key T
--theme-format {7}
--icons-key I
--icons-format {5}
--font-key F
--cursor-key C
-4
View File
@@ -1,4 +0,0 @@
--structure Host:Resolution:CPU:GPU:Memory:Disk:Battery
--memory-format "{?2}{2}{?}"
--disk-format "{?2}{2}{?}"
--battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}"
-10
View File
@@ -1,10 +0,0 @@
--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors"
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
--os-format "{3} {12}"
--resolution-format "{}x{}"
--de-format "{2} {3}"
--theme-format "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}"
--terminal-font-format "{/2}{-}{/}{2}{?3} {3}{?}"
--memory-format "{/1}{-}{/}{/2}{-}{/}{} / {}"
--gpu-key "GPU"
--resolution-key "Resolution"
-5
View File
@@ -1,5 +0,0 @@
--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Resolution:Terminal:Break:CPU:GPU:Memory:Break:Colors
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
--battery-format "{/4}{-}{/}{4}%{?5} [{5}]{?}"
--resolution-key "Resolution"
--gpu-key "GPU"
-1
View File
@@ -1 +0,0 @@
--structure OS:Kernel:Shell:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont
-30
View File
@@ -1,30 +0,0 @@
--os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; sys_vendor: {}
--kernel-format Sysname: {}; Release: {}; Version: {}
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
--processes-format Count: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
--resolution-format Width: {}; Height: {}; Refresh rate: {}
--de-format Process name: {}; Pretty name: {}; Version: {}
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
--wm-theme-format Name: {}
--theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
--icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
--font-format Font1: {}; Font2: {}; Font3: {}; Font4: {}
--cursor-format Theme: {}; Size: {}
--terminal-format Process: {}; Path: {}; Exe: {}
--terminal-font-format Pretty: {}; Name: {}; Size: {}; Styles: {}
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
--cpu-usage-format Percentage: {}
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}
--memory-format Used: {}; Total: {}; Percentage: {}
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; Removable: {}; Hidden: {}; Filesystem: {}; Name: {}
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
--poweradapter-format Watts: {}; Name: {}; Manufactor: {}; Model: {}; Description: {}
--player-format Pretty: {}; Name: {}; Bus: {}; Url: {}
--media-format Pretty: {}; Name: {}; Artist: {}; Album: {}
--datetime-format year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
--opengl-format version: {}; renderer: {}; vendor: {}
--opencl-format version: {}; device: {}; vendor: {}
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env sh
set -e
mkdir -p build/
cd build/
if [ -z "${CMAKE_BUILD_TYPE}" ]; then
CMAKE_BUILD_TYPE=Release
fi
cmake "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" ..
if [ -z "$OSTYPE" ] || [ "$OSTYPE" = "linux-gnu" ]; then
cmake_build_args="-j$(nproc)"
elif [ "$OSTYPE" = "darwin" ]; then
cmake_build_args="-j$(sysctl -n hw.ncpu)"
else
cmake_build_args=""
fi
cmake --build . --target fastfetch ${cmake_build_args}
./fastfetch "$@"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

-49
View File
@@ -1,49 +0,0 @@
#include "util/textModifier.h"
#include "bar.h"
// green, yellow, red: print the color on nth (0~9) block
// set its value == 10 means the color will not be printed
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red)
{
assert(green <= 10 && yellow <= 10 && red <= 10);
// [ 0%, 5%) prints 0 blocks
// [ 5%, 15%) prints 1 block;
// ...
// [85%, 95%) prints 9 blocks;
// [95%,100%] prints 10 blocks
percent = (uint8_t)(percent + 5) / 10;
assert(percent <= 10);
if(!instance->config.pipe)
ffStrbufAppendS(buffer, "\033[97m[ ");
else
ffStrbufAppendS(buffer, "[ ");
for (uint8_t i = 0; i < percent; ++i)
{
if(!instance->config.pipe)
{
if (i == green)
ffStrbufAppendS(buffer, "\033[32m");
else if (i == yellow)
ffStrbufAppendS(buffer, "\033[93m");
else if (i == red)
ffStrbufAppendS(buffer, "\033[91m");
}
ffStrbufAppendS(buffer, "■");
}
if (percent < 10)
{
if(!instance->config.pipe)
ffStrbufAppendS(buffer, "\033[97m");
for (uint8_t i = percent; i < 10; ++i)
ffStrbufAppendS(buffer, "-");
}
if(!instance->config.pipe)
ffStrbufAppendS(buffer, "\033[97m ]" FASTFETCH_TEXT_MODIFIER_RESET);
else
ffStrbufAppendS(buffer, " ]");
}
-16
View File
@@ -1,16 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_bar
#define FF_INCLUDED_common_bar
#include "fastfetch.h"
enum
{
FF_PERCENTAGE_TYPE_NUM_BIT = 1,
FF_PERCENTAGE_TYPE_BAR_BIT = 2,
};
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
#endif
-233
View File
@@ -1,233 +0,0 @@
#include "fastfetch.h"
#include "common/font.h"
#include <string.h>
static void fontInit(FFfont* font)
{
ffStrbufInit(&font->pretty);
ffStrbufInit(&font->name);
ffStrbufInitA(&font->size, 4);
ffListInitA(&font->styles, sizeof(FFstrbuf), 4);
}
static void fontInitPretty(FFfont* font)
{
ffStrbufAppend(&font->pretty, &font->name);
if(font->size.length == 0 && font->styles.length == 0)
return;
else if(font->pretty.length == 0)
ffStrbufAppendS(&font->pretty, "default");
ffStrbufAppendS(&font->pretty, " (");
if(font->size.length > 0)
{
ffStrbufAppend(&font->pretty, &font->size);
ffStrbufAppendS(&font->pretty, "pt");
if(font->styles.length > 0)
ffStrbufAppendS(&font->pretty, ", ");
}
for(uint32_t i = 0; i < font->styles.length; i++)
{
ffStrbufAppend(&font->pretty, ffListGet(&font->styles, i));
if(i < font->styles.length - 1)
ffStrbufAppendS(&font->pretty, ", ");
}
ffStrbufAppendC(&font->pretty, ')');
}
void ffFontInitQt(FFfont* font, const char* data)
{
fontInit(font);
//See https://doc.qt.io/qt-5/qfont.html#toString
//Family
while(*data != ',' && *data != '\0')
{
ffStrbufAppendC(&font->name, *data);
++data;
}
if(*data != '\0')
++data;
ffStrbufTrim(&font->name, ' ');
//Size
while(*data != ',' && *data != '\0')
{
ffStrbufAppendC(&font->size, *data);
++data;
}
if(*data != '\0')
++data;
ffStrbufTrim(&font->size, ' ');
#define FF_FONT_QT_SKIP_VALUE \
while(*data != ',' && *data != '\0') \
++data; \
if(*data != '\0') \
++data;
FF_FONT_QT_SKIP_VALUE //Pixel size
FF_FONT_QT_SKIP_VALUE //Style hint
FF_FONT_QT_SKIP_VALUE //Font weight
FF_FONT_QT_SKIP_VALUE //Font style
FF_FONT_QT_SKIP_VALUE //Underline
FF_FONT_QT_SKIP_VALUE //Strike out
FF_FONT_QT_SKIP_VALUE //Fixed pitch
FF_FONT_QT_SKIP_VALUE //Always 0
#undef FF_FONT_QT_SKIP_VALUE
while(*data != '\0')
{
while(*data == ' ')
++data;
if(*data == '\0')
break;
FFstrbuf* style = ffListAdd(&font->styles);
ffStrbufInit(style);
while(*data != ' ' && *data != '\0')
{
ffStrbufAppendC(style, *data);
++data;
}
}
fontInitPretty(font);
}
static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* alternativeBuffer)
{
while(**data == ' ' || **data == '\t' || **data == ',')
++(*data);
const char* wordStart = *data;
while(**data != ' ' && **data != '\t' && **data != ',' && **data != '\0' && **data != '`' && **data != '\\')
++(*data);
uint32_t wordLength = (uint32_t) (*data - wordStart);
if(wordLength == 0)
return;
if(**data == '\0' || **data == '`' || **data == '\\')
{
ffStrbufAppendNS(&font->size, wordLength, wordStart);
if(ffStrbufEndsWithS(&font->size, "px"))
ffStrbufSubstrBefore(&font->size, font->size.length - 2);
double dummy;
if(sscanf(font->size.chars, "%lf", &dummy) == 1)
return;
ffStrbufClear(&font->size);
}
if(
strncasecmp(wordStart, "Ultra", 5) == 0 ||
strncasecmp(wordStart, "Extra", 5) == 0 ||
strncasecmp(wordStart, "Semi", 4) == 0 ||
strncasecmp(wordStart, "Demi", 4) == 0 ||
strncasecmp(wordStart, "Normal", wordLength) == 0 ||
strncasecmp(wordStart, "Roman", wordLength) == 0 ||
strncasecmp(wordStart, "Oblique", wordLength) == 0 ||
strncasecmp(wordStart, "Italic", wordLength) == 0 ||
strncasecmp(wordStart, "Thin", wordLength) == 0 ||
strncasecmp(wordStart, "Light", wordLength) == 0 ||
strncasecmp(wordStart, "Bold", wordLength) == 0 ||
strncasecmp(wordStart, "Black", wordLength) == 0 ||
strncasecmp(wordStart, "Condensed", wordLength) == 0 ||
strncasecmp(wordStart, "Expanded", wordLength) == 0
) {
if(alternativeBuffer == NULL)
{
alternativeBuffer = ffListAdd(&font->styles);
ffStrbufInit(alternativeBuffer);
}
ffStrbufAppendNSExludingC(alternativeBuffer, wordLength, wordStart, '-');
if(
strncasecmp(wordStart, "Ultra ", 6) == 0 ||
strncasecmp(wordStart, "Extra ", 6) == 0 ||
strncasecmp(wordStart, "Semi ", 5) == 0 ||
strncasecmp(wordStart, "Demi ", 5) == 0
) {
fontPangoParseWord(data, font, alternativeBuffer);
}
return;
}
if(alternativeBuffer != NULL)
{
ffStrbufAppendNSExludingC(alternativeBuffer, wordLength, wordStart, '-');
return;
}
if(font->name.length > 0)
ffStrbufAppendC(&font->name, ' ');
ffStrbufAppendNS(&font->name, wordLength, wordStart);
}
void ffFontInitPango(FFfont* font, const char* data)
{
fontInit(font);
while(*data != '\0' && *data != '`' && *data != '\\')
fontPangoParseWord(&data, font, NULL);
fontInitPretty(font);
}
void ffFontInitValues(FFfont* font, const char* name, const char* size)
{
fontInit(font);
ffStrbufAppendS(&font->name, name);
ffStrbufAppendS(&font->size, size);
fontInitPretty(font);
}
void ffFontInitCopy(FFfont* font, const char* name)
{
ffFontInitValues(font, name, NULL);
}
void ffFontInitWithSpace(FFfont* font, const char* rawName)
{
const char* pspace = strrchr(rawName, ' ');
if(pspace == NULL)
{
ffFontInitCopy(font, rawName);
return;
}
fontInit(font);
ffStrbufAppendNS(&font->name, (uint32_t)(pspace - rawName), rawName);
ffStrbufAppendS(&font->size, pspace + 1);
fontInitPretty(font);
}
void ffFontDestroy(FFfont* font)
{
ffStrbufDestroy(&font->pretty);
ffStrbufDestroy(&font->name);
ffStrbufDestroy(&font->size);
for(uint32_t i = 0; i < font->styles.length; i++)
ffStrbufDestroy(ffListGet(&font->styles, i));
ffListDestroy(&font->styles);
}
-24
View File
@@ -1,24 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_font
#define FF_INCLUDED_common_font
#include "util/FFstrbuf.h"
#include "util/FFlist.h"
typedef struct FFfont
{
FFstrbuf pretty;
FFstrbuf name;
FFstrbuf size;
FFlist styles;
} FFfont;
void ffFontInitQt(FFfont* font, const char* data);
void ffFontInitPango(FFfont* font, const char* data);
void ffFontInitCopy(FFfont* font, const char* name);
void ffFontInitValues(FFfont* font, const char* name, const char* size);
void ffFontInitWithSpace(FFfont* font, const char* rawName);
void ffFontDestroy(FFfont* font);
#endif
-274
View File
@@ -1,274 +0,0 @@
#include "fastfetch.h"
#include "common/format.h"
#include "common/parsing.h"
#include "util/textModifier.h"
#include <inttypes.h>
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
{
if(formatarg->type == FF_FORMAT_ARG_TYPE_INT)
ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT)
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
ffStrbufAppendF(buffer, "%" PRIu8, *(uint8_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRING)
ffStrbufAppendS(buffer, (const char*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRBUF)
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_DOUBLE)
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_BOOL)
ffStrbufAppendS(buffer, formatarg->value != NULL ? "true" : "false");
else if(formatarg->type == FF_FORMAT_ARG_TYPE_LIST)
{
const FFlist* list = formatarg->value;
for(uint32_t i = 0; i < list->length; i++)
{
ffStrbufAppend(buffer, ffListGet(list, i));
if(i < list->length - 1)
ffStrbufAppendS(buffer, ", ");
}
}
else if(formatarg->type != FF_FORMAT_ARG_TYPE_NULL)
{
fprintf(stderr, "Error: format string \"%s\": argument is not implemented: %i\n", buffer->chars, formatarg->type);
}
}
/**
* @brief parses a string to a uint32_t
*
* If the string can't be parsed, or is < 1, uint32_t max is returned.
*
* @param placeholderValue the string to parse
* @return uint32_t the parsed value
*/
static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
{
uint32_t result = UINT32_MAX;
if(placeholderValue->chars[0] != '-')
sscanf(placeholderValue->chars, "%u", &result);
return result == 0 ? UINT32_MAX : result;
}
static inline void appendInvalidPlaceholder(FFstrbuf* buffer, const char* start, const FFstrbuf* placeholderValue, uint32_t index, uint32_t formatStringLength)
{
ffStrbufAppendS(buffer, start);
ffStrbufAppend(buffer, placeholderValue);
if(index < formatStringLength)
ffStrbufAppendC(buffer, '}');
}
static inline void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placeholder, uint32_t* argCounter, uint32_t numArgs, const FFformatarg* arguments)
{
if(*argCounter >= numArgs)
ffStrbufAppendS(buffer, placeholder);
else
ffFormatAppendFormatArg(buffer, arguments + *argCounter);
(*argCounter)++;
}
static inline bool formatArgSet(const FFformatarg* arg)
{
return arg->value != NULL && (
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
(arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet(arg->value)) ||
(arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_BOOL && arg->value != NULL)
);
}
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments)
{
uint32_t argCounter = 0;
uint32_t numOpenIfs = 0;
uint32_t numOpenNotIfs = 0;
uint32_t numOpenColors = 0;
for(uint32_t i = 0; i < formatstr->length; ++i)
{
// if we don't have a placeholder start just copy the chars over to output buffer
if(formatstr->chars[i] != '{')
{
ffStrbufAppendC(buffer, formatstr->chars[i]);
continue;
}
// if we have an { at the end handle it as {}
if(i == formatstr->length - 1)
{
appendEmptyPlaceholder(buffer, "{", &argCounter, numArgs, arguments);
continue;
}
// jump to next char, the start of the placeholder value
++i;
// double {{ elvaluates to a single { and doesn't count as start
if(formatstr->chars[i] == '{')
{
ffStrbufAppendC(buffer, '{');
continue;
}
// placeholder is {}
if(formatstr->chars[i] == '}')
{
appendEmptyPlaceholder(buffer, "{}", &argCounter, numArgs, arguments);
continue;
}
FFstrbuf placeholderValue;
ffStrbufInit(&placeholderValue);
while(i < formatstr->length && formatstr->chars[i] != '}')
ffStrbufAppendC(&placeholderValue, formatstr->chars[i++]);
// test if for stop, if so break the loop
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '-')
{
ffStrbufDestroy(&placeholderValue);
break;
}
// test for end of an if, if so do nothing
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '?')
{
if(numOpenIfs == 0)
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
else
--numOpenIfs;
ffStrbufDestroy(&placeholderValue);
continue;
}
// test for end of a not if, if so do nothing
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '/')
{
if(numOpenNotIfs == 0)
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
else
--numOpenNotIfs;
ffStrbufDestroy(&placeholderValue);
continue;
}
// test for end of a color, if so do nothing
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '#')
{
if(numOpenColors == 0)
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
else
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
--numOpenColors;
}
ffStrbufDestroy(&placeholderValue);
continue;
}
// test for if, if so evaluate it
if(placeholderValue.chars[0] == '?')
{
ffStrbufSubstrAfter(&placeholderValue, 0);
uint32_t index = getArgumentIndex(&placeholderValue);
// testing for an invalid index
if(index > numArgs)
{
appendInvalidPlaceholder(buffer, "{?", &placeholderValue, i, formatstr->length);
ffStrbufDestroy(&placeholderValue);
continue;
}
// continue normally if an format arg is set and the value is > 0
if(formatArgSet(&arguments[index - 1]))
{
++numOpenIfs;
ffStrbufDestroy(&placeholderValue);
continue;
}
// fastforward to the end of the if without printing the in between
i = ffStrbufNextIndexS(formatstr, i, "{?}") + 2; // 2 is the length of "{?}" - 1 because the loop will increament it again directly after continue
ffStrbufDestroy(&placeholderValue);
continue;
}
// test for not if, if so evaluate it
if(placeholderValue.chars[0] == '/')
{
ffStrbufSubstrAfter(&placeholderValue, 0);
uint32_t index = getArgumentIndex(&placeholderValue);
// testing for an invalid index
if(index > numArgs)
{
appendInvalidPlaceholder(buffer, "{/", &placeholderValue, i, formatstr->length);
ffStrbufDestroy(&placeholderValue);
continue;
}
//continue normally if an format arg is not set or the value is 0
if(!formatArgSet(&arguments[index - 1]))
{
++numOpenNotIfs;
ffStrbufDestroy(&placeholderValue);
continue;
}
// fastforward to the end of the if without printing the in between
i = ffStrbufNextIndexS(formatstr, i, "{/}") + 2; // 2 is the length of "{/}" - 1 because the loop will increament it again directly after continue
ffStrbufDestroy(&placeholderValue);
continue;
}
//test for color, if so evaluate it
if(placeholderValue.chars[0] == '#')
{
++numOpenColors;
ffStrbufSubstrAfter(&placeholderValue, 0);
ffStrbufAppendS(buffer, "\033[");
ffStrbufAppend(buffer, &placeholderValue);
ffStrbufAppendC(buffer, 'm');
ffStrbufDestroy(&placeholderValue);
continue;
}
uint32_t index = getArgumentIndex(&placeholderValue);
// test for invalid index
if(index > numArgs)
{
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
ffStrbufDestroy(&placeholderValue);
continue;
}
ffFormatAppendFormatArg(buffer, &arguments[index - 1]);
ffStrbufDestroy(&placeholderValue);
}
ffStrbufTrimRight(buffer, ' ');
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
-31
View File
@@ -1,31 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_format
#define FF_INCLUDED_common_format
typedef enum FFformatargtype
{
FF_FORMAT_ARG_TYPE_NULL = 0,
FF_FORMAT_ARG_TYPE_UINT,
FF_FORMAT_ARG_TYPE_UINT16,
FF_FORMAT_ARG_TYPE_UINT8,
FF_FORMAT_ARG_TYPE_INT,
FF_FORMAT_ARG_TYPE_STRING,
FF_FORMAT_ARG_TYPE_STRBUF,
FF_FORMAT_ARG_TYPE_DOUBLE,
FF_FORMAT_ARG_TYPE_LIST,
FF_FORMAT_ARG_TYPE_BOOL
} FFformatargtype;
typedef struct FFformatarg
{
FFformatargtype type;
const void* value;
} FFformatarg;
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
#define FF_FORMAT_ARG_VALUE_BOOL(xpr) ((xpr) ? (const void*) 1 : NULL)
#endif
-559
View File
@@ -1,559 +0,0 @@
#include "fastfetch.h"
#include "common/parsing.h"
#include "common/thread.h"
#include "detection/qt.h"
#include "detection/gtk.h"
#include "detection/displayserver/displayserver.h"
#include "util/textModifier.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <wincon.h>
#include <locale.h>
#else
#include <signal.h>
#endif
static void initConfigDirs(FFstate* state)
{
ffListInit(&state->configDirs, sizeof(FFstrbuf));
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
if(ffStrSet(xdgConfigHome))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigHome);
ffStrbufEnsureEndsWithC(buffer, '/');
}
#endif
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
if(ffListFirstIndexComp(&state->configDirs, element, (bool(*)(const void*, const void*))ffStrbufEqual) < state->configDirs.length - 1) \
{ \
ffStrbufDestroy(ffListGet(&state->configDirs, state->configDirs.length - 1)); \
--state->configDirs.length; \
}
FFstrbuf* userConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userConfigHome, 64);
ffStrbufAppendS(userConfigHome, state->passwd->pw_dir);
ffStrbufAppendS(userConfigHome, "/.config/");
FF_ENSURE_ONLY_ONCE_IN_LIST(userConfigHome)
FFstrbuf* userHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userHome, 64);
ffStrbufAppendS(userHome, state->passwd->pw_dir);
ffStrbufEnsureEndsWithC(userHome, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(userHome)
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
FFstrbuf xdgConfigDirs;
ffStrbufInitA(&xdgConfigDirs, 64);
ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS"));
uint32_t startIndex = 0;
while (startIndex < xdgConfigDirs.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':');
xdgConfigDirs.chars[colonIndex] = '\0';
if(!ffStrSet(xdgConfigDirs.chars + startIndex))
{
startIndex = colonIndex + 1;
continue;
}
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex);
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(buffer);
startIndex = colonIndex + 1;
}
ffStrbufDestroy(&xdgConfigDirs);
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfigHome, 64);
ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ETC"/xdg/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome)
#endif
FFstrbuf* systemConfig = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfig, 64);
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
}
static void initState(FFstate* state)
{
#ifdef WIN32
//https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support
setlocale(LC_ALL, ".UTF8");
#endif
state->logoWidth = 0;
state->logoHeight = 0;
state->keysHeight = 0;
#ifndef WIN32
state->passwd = getpwuid(getuid());
#else
state->passwd = ffGetPasswd();
#endif
uname(&state->utsname);
initConfigDirs(state);
}
static void initModuleArg(FFModuleArgs* args)
{
ffStrbufInit(&args->key);
ffStrbufInit(&args->outputFormat);
ffStrbufInit(&args->errorFormat);
}
static void defaultConfig(FFinstance* instance)
{
ffStrbufInitA(&instance->config.logo.source, 0);
instance->config.logo.type = FF_LOGO_TYPE_AUTO;
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufInit(&instance->config.logo.colors[i]);
instance->config.logo.width = 0;
instance->config.logo.height = 0; //preserve aspect ratio
instance->config.logo.paddingLeft = 0;
instance->config.logo.paddingRight = 4;
instance->config.logo.printRemaining = true;
instance->config.logo.preserveAspectRadio = false;
instance->config.logo.chafaFgOnly = false;
ffStrbufInitS(&instance->config.logo.chafaSymbols, "block+border+space-wide-inverted"); // Chafa default
instance->config.logo.chafaCanvasMode = UINT32_MAX;
instance->config.logo.chafaColorSpace = UINT32_MAX;
instance->config.logo.chafaDitherMode = UINT32_MAX;
ffStrbufInit(&instance->config.colorKeys);
ffStrbufInit(&instance->config.colorTitle);
ffStrbufInit(&instance->config.separator);
ffStrbufAppendS(&instance->config.separator, ": ");
instance->config.showErrors = false;
instance->config.recache = false;
instance->config.allowSlowOperations = false;
instance->config.disableLinewrap = true;
instance->config.hideCursor = true;
instance->config.escapeBedrock = true;
instance->config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
instance->config.glType = FF_GL_TYPE_AUTO;
instance->config.pipe = false;
instance->config.multithreading = true;
instance->config.stat = false;
initModuleArg(&instance->config.os);
initModuleArg(&instance->config.host);
initModuleArg(&instance->config.bios);
initModuleArg(&instance->config.board);
initModuleArg(&instance->config.chassis);
initModuleArg(&instance->config.kernel);
initModuleArg(&instance->config.uptime);
initModuleArg(&instance->config.processes);
initModuleArg(&instance->config.packages);
initModuleArg(&instance->config.shell);
initModuleArg(&instance->config.resolution);
initModuleArg(&instance->config.de);
initModuleArg(&instance->config.wm);
initModuleArg(&instance->config.wmTheme);
initModuleArg(&instance->config.theme);
initModuleArg(&instance->config.icons);
initModuleArg(&instance->config.font);
initModuleArg(&instance->config.cursor);
initModuleArg(&instance->config.terminal);
initModuleArg(&instance->config.terminalFont);
initModuleArg(&instance->config.cpu);
initModuleArg(&instance->config.cpuUsage);
initModuleArg(&instance->config.gpu);
initModuleArg(&instance->config.memory);
initModuleArg(&instance->config.swap);
initModuleArg(&instance->config.disk);
initModuleArg(&instance->config.battery);
initModuleArg(&instance->config.powerAdapter);
initModuleArg(&instance->config.locale);
initModuleArg(&instance->config.localIP);
initModuleArg(&instance->config.publicIP);
initModuleArg(&instance->config.weather);
initModuleArg(&instance->config.wifi);
initModuleArg(&instance->config.player);
initModuleArg(&instance->config.media);
initModuleArg(&instance->config.dateTime);
initModuleArg(&instance->config.date);
initModuleArg(&instance->config.time);
initModuleArg(&instance->config.vulkan);
initModuleArg(&instance->config.openGL);
initModuleArg(&instance->config.openCL);
initModuleArg(&instance->config.users);
ffStrbufInitA(&instance->config.libPCI, 0);
ffStrbufInitA(&instance->config.libVulkan, 0);
ffStrbufInitA(&instance->config.libWayland, 0);
ffStrbufInitA(&instance->config.libXcbRandr, 0);
ffStrbufInitA(&instance->config.libXcb, 0);
ffStrbufInitA(&instance->config.libXrandr, 0);
ffStrbufInitA(&instance->config.libX11, 0);
ffStrbufInitA(&instance->config.libGIO, 0);
ffStrbufInitA(&instance->config.libDConf, 0);
ffStrbufInitA(&instance->config.libDBus, 0);
ffStrbufInitA(&instance->config.libXFConf, 0);
ffStrbufInitA(&instance->config.libSQLite3, 0);
ffStrbufInitA(&instance->config.librpm, 0);
ffStrbufInitA(&instance->config.libImageMagick, 0);
ffStrbufInitA(&instance->config.libZ, 0);
ffStrbufInitA(&instance->config.libChafa, 0);
ffStrbufInitA(&instance->config.libEGL, 0);
ffStrbufInitA(&instance->config.libGLX, 0);
ffStrbufInitA(&instance->config.libOSMesa, 0);
ffStrbufInitA(&instance->config.libOpenCL, 0);
ffStrbufInitA(&instance->config.libcJSON, 0);
ffStrbufInitA(&instance->config.libfreetype, 0);
ffStrbufInit(&instance->config.libwlanapi);
instance->config.cpuTemp = false;
instance->config.gpuTemp = false;
instance->config.batteryTemp = false;
instance->config.titleFQDN = false;
ffStrbufInitA(&instance->config.diskFolders, 0);
instance->config.diskShowRemovable = true;
instance->config.diskShowHidden = false;
ffStrbufInitA(&instance->config.batteryDir, 0);
ffStrbufInitA(&instance->config.separatorString, 0);
instance->config.localIpShowIpV4 = true;
instance->config.localIpShowIpV6 = false;
instance->config.localIpShowLoop = false;
ffStrbufInit(&instance->config.localIpNamePrefix);
instance->config.publicIpTimeout = 0;
ffStrbufInit(&instance->config.publicIpUrl);
instance->config.weatherTimeout = 0;
ffStrbufInitS(&instance->config.weatherOutputFormat, "%t+-+%C+(%l)");
ffStrbufInitA(&instance->config.osFile, 0);
ffStrbufInitA(&instance->config.playerName, 0);
instance->config.percentType = 1;
}
void ffInitInstance(FFinstance* instance)
{
initState(&instance->state);
defaultConfig(instance);
}
#ifdef FF_HAVE_THREADS
FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*)
#if !(defined(__APPLE__) || defined(_WIN32))
#define FF_DETECT_QT_GTK 1
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*)
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK2, FFinstance*)
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK3, FFinstance*)
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK4, FFinstance*)
#endif //!(defined(__APPLE__) || defined(_WIN32))
#endif //FF_HAVE_THREADS
void startDetectionThreads(FFinstance* instance)
{
#ifdef FF_HAVE_THREADS
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, instance));
#ifdef FF_DETECT_QT_GTK
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, instance));
#endif
#else
FF_UNUSED(instance);
#endif
}
static volatile bool ffDisableLinewrap = true;
static volatile bool ffHideCursor = true;
static void resetConsole()
{
if(ffDisableLinewrap)
fputs("\033[?7h", stdout);
if(ffHideCursor)
fputs("\033[?25h", stdout);
}
#ifdef _WIN32
BOOL WINAPI consoleHandler(DWORD signal)
{
FF_UNUSED(signal);
resetConsole();
exit(0);
}
#else
static void exitSignalHandler(int signal)
{
FF_UNUSED(signal);
resetConsole();
exit(0);
}
#endif
void ffStart(FFinstance* instance)
{
if(instance->config.multithreading)
startDetectionThreads(instance);
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
#ifdef _WIN32
#ifdef FF_ENABLE_BUFFER
setvbuf(stdout, NULL, _IOFBF, 4096);
#endif
SetConsoleCtrlHandler(consoleHandler, TRUE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
GetConsoleMode(hStdout, &mode);
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
SetConsoleOutputCP(CP_UTF8);
#else
#ifndef FF_ENABLE_BUFFER
setvbuf(stdout, NULL, _IONBF, 0);
#endif
struct sigaction action = { .sa_handler = exitSignalHandler };
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
sigaction(SIGQUIT, &action, NULL);
#endif
//reset everything to default before we start printing
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(ffHideCursor)
fputs("\033[?25l", stdout);
if(ffDisableLinewrap)
fputs("\033[?7l", stdout);
ffLogoPrint(instance);
}
void ffFinish(FFinstance* instance)
{
if(instance->config.logo.printRemaining)
ffLogoPrintRemaining(instance);
resetConsole();
}
static void destroyModuleArg(FFModuleArgs* args)
{
ffStrbufDestroy(&args->key);
ffStrbufDestroy(&args->outputFormat);
ffStrbufDestroy(&args->errorFormat);
}
static void destroyConfig(FFinstance* instance)
{
ffStrbufDestroy(&instance->config.logo.source);
ffStrbufDestroy(&instance->config.logo.chafaSymbols);
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufDestroy(&instance->config.logo.colors[i]);
ffStrbufDestroy(&instance->config.colorKeys);
ffStrbufDestroy(&instance->config.colorTitle);
ffStrbufDestroy(&instance->config.separator);
destroyModuleArg(&instance->config.os);
destroyModuleArg(&instance->config.host);
destroyModuleArg(&instance->config.bios);
destroyModuleArg(&instance->config.board);
destroyModuleArg(&instance->config.kernel);
destroyModuleArg(&instance->config.uptime);
destroyModuleArg(&instance->config.processes);
destroyModuleArg(&instance->config.packages);
destroyModuleArg(&instance->config.shell);
destroyModuleArg(&instance->config.resolution);
destroyModuleArg(&instance->config.de);
destroyModuleArg(&instance->config.wm);
destroyModuleArg(&instance->config.wmTheme);
destroyModuleArg(&instance->config.theme);
destroyModuleArg(&instance->config.icons);
destroyModuleArg(&instance->config.font);
destroyModuleArg(&instance->config.cursor);
destroyModuleArg(&instance->config.terminal);
destroyModuleArg(&instance->config.terminalFont);
destroyModuleArg(&instance->config.cpu);
destroyModuleArg(&instance->config.cpuUsage);
destroyModuleArg(&instance->config.gpu);
destroyModuleArg(&instance->config.memory);
destroyModuleArg(&instance->config.swap);
destroyModuleArg(&instance->config.disk);
destroyModuleArg(&instance->config.battery);
destroyModuleArg(&instance->config.powerAdapter);
destroyModuleArg(&instance->config.locale);
destroyModuleArg(&instance->config.localIP);
destroyModuleArg(&instance->config.publicIP);
destroyModuleArg(&instance->config.weather);
destroyModuleArg(&instance->config.wifi);
destroyModuleArg(&instance->config.player);
destroyModuleArg(&instance->config.media);
destroyModuleArg(&instance->config.dateTime);
destroyModuleArg(&instance->config.date);
destroyModuleArg(&instance->config.time);
destroyModuleArg(&instance->config.vulkan);
destroyModuleArg(&instance->config.openGL);
destroyModuleArg(&instance->config.openCL);
destroyModuleArg(&instance->config.users);
ffStrbufDestroy(&instance->config.libPCI);
ffStrbufDestroy(&instance->config.libVulkan);
ffStrbufDestroy(&instance->config.libWayland);
ffStrbufDestroy(&instance->config.libXcbRandr);
ffStrbufDestroy(&instance->config.libXcb);
ffStrbufDestroy(&instance->config.libXrandr);
ffStrbufDestroy(&instance->config.libX11);
ffStrbufDestroy(&instance->config.libGIO);
ffStrbufDestroy(&instance->config.libDConf);
ffStrbufDestroy(&instance->config.libDBus);
ffStrbufDestroy(&instance->config.libXFConf);
ffStrbufDestroy(&instance->config.libSQLite3);
ffStrbufDestroy(&instance->config.librpm);
ffStrbufDestroy(&instance->config.libImageMagick);
ffStrbufDestroy(&instance->config.libZ);
ffStrbufDestroy(&instance->config.libChafa);
ffStrbufDestroy(&instance->config.libEGL);
ffStrbufDestroy(&instance->config.libGLX);
ffStrbufDestroy(&instance->config.libOSMesa);
ffStrbufDestroy(&instance->config.libOpenCL);
ffStrbufDestroy(&instance->config.libcJSON);
ffStrbufDestroy(&instance->config.libfreetype);
ffStrbufDestroy(&instance->config.libwlanapi);
ffStrbufDestroy(&instance->config.diskFolders);
ffStrbufDestroy(&instance->config.batteryDir);
ffStrbufDestroy(&instance->config.separatorString);
ffStrbufDestroy(&instance->config.localIpNamePrefix);
ffStrbufDestroy(&instance->config.publicIpUrl);
ffStrbufDestroy(&instance->config.weatherOutputFormat);
ffStrbufDestroy(&instance->config.osFile);
ffStrbufDestroy(&instance->config.playerName);
}
static void destroyState(FFinstance* instance)
{
for(uint32_t i = 0; i < instance->state.configDirs.length; ++i)
ffStrbufDestroy((FFstrbuf*)ffListGet(&instance->state.configDirs, i));
ffListDestroy(&instance->state.configDirs);
}
void ffDestroyInstance(FFinstance* instance)
{
destroyConfig(instance);
destroyState(instance);
}
//Must be in a file compiled with the libfastfetch target, because the FF_HAVE* macros are not defined for the executable targets
void ffListFeatures()
{
fputs(
#ifdef FF_HAVE_LIBPCI
"libpci\n"
#endif
#ifdef FF_HAVE_VULKAN
"vulkan\n"
#endif
#ifdef FF_HAVE_WAYLAND
"wayland\n"
#endif
#ifdef FF_HAVE_XCB_RANDR
"xcb-randr\n"
#endif
#ifdef FF_HAVE_XCB
"xcb\n"
#endif
#ifdef FF_HAVE_XRANDR
"xrandr\n"
#endif
#ifdef FF_HAVE_X11
"x11\n"
#endif
#ifdef FF_HAVE_GIO
"gio\n"
#endif
#ifdef FF_HAVE_DCONF
"dconf\n"
#endif
#ifdef FF_HAVE_DBUS
"dbus\n"
#endif
#ifdef FF_HAVE_IMAGEMAGICK7
"imagemagick7\n"
#endif
#ifdef FF_HAVE_IMAGEMAGICK6
"imagemagick6\n"
#endif
#ifdef FF_HAVE_CHAFA
"chafa\n"
#endif
#ifdef FF_HAVE_ZLIB
"zlib\n"
#endif
#ifdef FF_HAVE_XFCONF
"xfconf\n"
#endif
#ifdef FF_HAVE_SQLITE3
"sqlite3\n"
#endif
#ifdef FF_HAVE_RPM
"rpm\n"
#endif
#ifdef FF_HAVE_EGL
"egl\n"
#endif
#ifdef FF_HAVE_GLX
"glx\n"
#endif
#ifdef FF_HAVE_OSMESA
"osmesa\n"
#endif
#ifdef FF_HAVE_OPENCL
"opencl\n"
#endif
#ifdef FF_HAVE_LIBCJSON
"libcjson\n"
#endif
#ifdef FF_HAVE_FREETYPE
"freetype"
#endif
""
, stdout);
}
-285
View File
@@ -1,285 +0,0 @@
#include "fastfetch.h"
#include "common/io.h"
#include <unistd.h>
#include <fcntl.h>
#ifdef _WIN32
#include <fileapi.h>
#else
#include <termios.h>
#include <poll.h>
#endif
static void createSubfolders(const char* fileName)
{
FFstrbuf path;
ffStrbufInit(&path);
while(*fileName != '\0')
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
{
mkdir(path.chars
#ifndef WIN32
, S_IRWXU | S_IRGRP | S_IROTH
#endif
);
}
++fileName;
}
ffStrbufDestroy(&path);
}
bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
{
return write(fd, content->chars, content->length) != -1;
}
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
{
#ifdef _WIN32
HANDLE handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
createSubfolders(fileName);
handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
}
DWORD written;
bool ret = !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL);
CloseHandle(handle);
#else
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open(fileName, openFlagsModes, openFlagsRights);
if(fd == -1)
{
createSubfolders(fileName);
fd = open(fileName, openFlagsModes, openFlagsRights);
if(fd == -1)
return false;
}
bool ret = write(fd, data, dataSize) != -1;
close(fd);
#endif
return ret;
}
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
{
return ffWriteFileData(fileName, buffer->length, buffer->chars);
}
#ifdef _WIN32
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer)
{
DWORD readed = 0;
LARGE_INTEGER fileSize;
if(!GetFileSizeEx(handle, &fileSize))
fileSize.QuadPart = 0;
ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31);
uint32_t free = ffStrbufGetFree(buffer);
bool success;
while(
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return success;
}
#endif
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
{
ssize_t readed = 0;
struct stat fileInfo;
if(fstat(fd, &fileInfo) != 0)
return false;
ffStrbufEnsureFree(buffer, fileInfo.st_size > 0 ? (uint32_t)fileInfo.st_size : 31);
uint32_t free = ffStrbufGetFree(buffer);
while(
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return readed >= 0;
}
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
{
#ifdef _WIN32
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
DWORD readed;
if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL))
return -1;
return (ssize_t)readed;
#else
int fd = open(fileName, O_RDONLY);
if(fd == -1)
return -1;
ssize_t readed = read(fd, data, dataSize);
close(fd);
return readed;
#endif
}
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
{
#ifdef _WIN32
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
bool ret = ffAppendHandleBuffer(handle, buffer);
CloseHandle(handle);
#else
int fd = open(fileName, O_RDONLY);
if(fd == -1)
return false;
bool ret = ffAppendFDBuffer(fd, buffer);
close(fd);
#endif
return ret;
}
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFileBuffer(fileName, buffer);
}
// Not thread safe!
void ffSuppressIO(bool suppress)
{
static bool init = false;
static int origOut = -1;
static int origErr = -1;
static int nullFile = -1;
if(!init)
{
if(!suppress)
return;
origOut = dup(STDOUT_FILENO);
origErr = dup(STDERR_FILENO);
nullFile = open("/dev/null", O_WRONLY);
init = true;
}
if(nullFile == -1)
return;
fflush(stdout);
fflush(stderr);
dup2(suppress ? nullFile : origOut, STDOUT_FILENO);
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
}
bool ffFileExists(const char* fileName, mode_t mode)
{
struct stat fileStat;
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
}
void ffGetTerminalResponse(const char* request, const char* format, ...)
{
#ifndef WIN32
struct termios oldTerm, newTerm;
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
return;
fputs(request, stdout);
fflush(stdout);
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN;
pfd.revents = 0;
//Give the terminal 35ms to respond
if(poll(&pfd, 1, 35) <= 0)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
return;
}
char buffer[512];
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
if(readed <= 0)
return;
buffer[readed] = '\0';
va_list args;
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
#else
//Unimplemented
FF_UNUSED(request, format);
#endif
}
-30
View File
@@ -1,30 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_io
#define FF_INCLUDED_common_io
#include "fastfetch.h"
#include <sys/stat.h> //mode_t, fstat, stat
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer);
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer);
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer);
#ifdef _WIN32
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer);
#endif
bool ffFileExists(const char* fileName, mode_t mode);
// Not thread safe!
void ffSuppressIO(bool suppress);
FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...);
#endif
-82
View File
@@ -1,82 +0,0 @@
#include "fastfetch.h"
#include "common/library.h"
#include <stdarg.h>
//Clang doesn't define __SANITIZE_ADDRESS__ but defines __has_feature(address_sanitizer)
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define __SANITIZE_ADDRESS__
#endif
#endif
#ifndef FF_DLOPEN_FLAGS
#ifdef __SANITIZE_ADDRESS__
#define FF_DLOPEN_FLAGS RTLD_LAZY | RTLD_NODELETE
#else
#define FF_DLOPEN_FLAGS RTLD_LAZY
#endif
#endif
static void* libraryLoad(const char* path, int maxVersion)
{
void* result = dlopen(path, FF_DLOPEN_FLAGS);
#ifdef _WIN32
// libX.dll.1 never exists on Windows, while libX-1.dll may exist
FF_UNUSED(maxVersion)
#else
if(result != NULL || maxVersion < 0)
return result;
FFstrbuf pathbuf;
ffStrbufInitA(&pathbuf, 64);
ffStrbufAppendS(&pathbuf, path);
ffStrbufAppendC(&pathbuf, '.');
for(int i = maxVersion; i >= 0; --i)
{
uint32_t originalLength = pathbuf.length;
ffStrbufAppendF(&pathbuf, "%i", i);
result = dlopen(pathbuf.chars, FF_DLOPEN_FLAGS);
if(result != NULL)
break;
ffStrbufSubstrBefore(&pathbuf, originalLength);
}
ffStrbufDestroy(&pathbuf);
#endif
return result;
}
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...)
{
if(userProvidedName != NULL && userProvidedName->length > 0)
return dlopen(userProvidedName->chars, FF_DLOPEN_FLAGS);
va_list defaultNames;
va_start(defaultNames, userProvidedName);
void* result = NULL;
while(result == NULL)
{
const char* path = va_arg(defaultNames, const char*);
if(path == NULL)
break;
int maxVersion = va_arg(defaultNames, int);
result = libraryLoad(path, maxVersion);
}
va_end(defaultNames);
return result;
}
-63
View File
@@ -1,63 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_library
#define FF_INCLUDED_common_library
#include "fastfetch.h"
#include "util/FFcheckmacros.h"
#if defined(_WIN32) //We don't force MSYS using LoadLibrary because dlopen also searches $LD_LIBRARY_PATH
#include <libloaderapi.h>
#define FF_DLOPEN_FLAGS 0
FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); }
FF_C_NODISCARD static inline void* dlsym(void* handle, const char* symbol) { return GetProcAddress((HMODULE)handle, symbol); }
static inline int dlclose(void* handle) { return !FreeLibrary((HMODULE)handle); }
#else
#include <dlfcn.h>
#endif
#ifdef _WIN32
#define FF_LIBRARY_EXTENSION ".dll"
#elif defined(__APPLE__)
#define FF_LIBRARY_EXTENSION ".dylib"
#else
#define FF_LIBRARY_EXTENSION ".so"
#endif
#define FF_LIBRARY_SYMBOL(symbolName) \
__typeof__(&symbolName) ff ## symbolName;
#define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \
void* libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
if(libraryObjectName == NULL) \
return returnValue;
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
symbolMapping = dlsym(library, #symbolName); \
if(symbolMapping == NULL) \
{ \
dlclose(library); \
return returnValue; \
}
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
#define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
__typeof__(&symbolName) ff ## symbolName = dlsym(library, #symbolName);
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
#define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, returnValue);
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName->ff ## symbolName, symbolName, returnValue);
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...);
#endif
-39
View File
@@ -1,39 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_networking
#define FF_INCLUDED_common_networking
#include "common/thread.h"
#include "util/FFstrbuf.h"
#ifdef _WIN32
#include <minwindef.h>
#endif
typedef struct FFNetworkingState {
#ifdef _WIN32
uintptr_t sockfd;
OVERLAPPED overlapped;
#else
int sockfd;
FFstrbuf host;
FFstrbuf command;
#ifdef FF_HAVE_THREADS
FFThreadType thread;
#endif
#endif
} FFNetworkingState;
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout);
static inline bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer)
{
FFNetworkingState state;
if(ffNetworkingSendHttpRequest(&state, host, path, headers))
return ffNetworkingRecvHttpResponse(&state, buffer, timeout);
return false;
}
#endif
-103
View File
@@ -1,103 +0,0 @@
#include "fastfetch.h"
#include "common/networking.h"
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
static void connectAndSend(FFNetworkingState* state)
{
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo* addr;
if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0)
goto error;
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(state->sockfd == -1)
{
freeaddrinfo(addr);
goto error;
}
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
{
close(state->sockfd);
freeaddrinfo(addr);
goto error;
}
freeaddrinfo(addr);
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
{
close(state->sockfd);
goto error;
}
goto exit;
error:
state->sockfd = -1;
exit:
ffStrbufDestroy(&state->host);
ffStrbufDestroy(&state->command);
}
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
{
ffStrbufInitS(&state->host, host);
ffStrbufInitA(&state->command, 64);
ffStrbufAppendS(&state->command, "GET ");
ffStrbufAppendS(&state->command, path);
ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&state->command, host);
ffStrbufAppendS(&state->command, "\r\n");
ffStrbufAppendS(&state->command, headers);
ffStrbufAppendS(&state->command, "\r\n");
#ifdef FF_HAVE_THREADS
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
return !!state->thread;
#else
connectAndSend(state);
return state->sockfd != -1;
#endif
}
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
{
#ifdef FF_HAVE_THREADS
ffThreadJoin(state->thread);
#endif
if(state->sockfd == -1)
return false;
if(timeout > 0)
{
struct timeval timev;
timev.tv_sec = 0;
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
}
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
if(received > 0)
{
buffer->length += (uint32_t) received;
buffer->chars[buffer->length] = '\0';
}
close(state->sockfd);
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
}
-125
View File
@@ -1,125 +0,0 @@
#include <mswsock.h>
#include <ws2tcpip.h>
//Must be included after <mswsock.h>
#include "fastfetch.h"
#include "common/networking.h"
static LPFN_CONNECTEX ConnectEx;
static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context)
{
(void)once;
(void)param;
static WSADATA wsaData;
*context = &wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return FALSE;
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
return FALSE;
//Dummy socket needed for WSAIoctl
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == INVALID_SOCKET)
return FALSE;
DWORD dwBytes;
GUID guid = WSAID_CONNECTEX;
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid),
&ConnectEx, sizeof(ConnectEx),
&dwBytes, NULL, NULL) != 0)
return FALSE;
return closesocket(sockfd) == 0;
}
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
{
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
WSADATA* pData;
if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData))
return false;
memset(state, 0, sizeof(*state));
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo* addr;
if(getaddrinfo(host, "80", &hints, &addr) != 0)
return false;
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(state->sockfd == INVALID_SOCKET)
{
freeaddrinfo(addr);
return false;
}
{
//ConnectEx requires the socket to be initially bound
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = INADDR_ANY,
.sin_port = 0,
};
if(bind(state->sockfd, (SOCKADDR *)&addr, sizeof(addr)) != 0)
{
printf("bind %d\n", WSAGetLastError());
return false;
}
}
FF_STRBUF_AUTO_DESTROY command;
ffStrbufInitA(&command, 64);
ffStrbufAppendS(&command, "GET ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&command, host);
ffStrbufAppendS(&command, "\r\n");
ffStrbufAppendS(&command, headers);
ffStrbufAppendS(&command, "\r\n");
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped);
freeaddrinfo(addr);
if(!result && WSAGetLastError() != WSA_IO_PENDING)
{
closesocket(state->sockfd);
return false;
}
return true;
}
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
{
DWORD transfer, flags;
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
{
closesocket(state->sockfd);
return false;
}
if(timeout > 0)
{
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
}
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
if(received > 0)
{
buffer->length += (uint32_t) received;
buffer->chars[buffer->length] = '\0';
}
closesocket(state->sockfd);
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
}
-177
View File
@@ -1,177 +0,0 @@
#include "fastfetch.h"
#include "common/parsing.h"
#include <ctype.h>
#include <inttypes.h>
bool ffStrSet(const char* str)
{
if(str == NULL)
return false;
while(isspace(*str))
str++;
return *str != '\0';
}
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
{
if(major->length > 0)
ffStrbufAppend(buffer, major);
else if(minor->length > 0 || patch->length > 0)
ffStrbufAppendC(buffer, '1');
if(minor->length == 0 && patch->length == 0)
return;
ffStrbufAppendC(buffer, '.');
if(minor->length > 0)
ffStrbufAppend(buffer, minor);
else if(patch->length > 0)
ffStrbufAppendC(buffer, '0');
if(patch->length == 0)
return;
ffStrbufAppendC(buffer, '.');
ffStrbufAppend(buffer, patch);
}
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2)
{
if(version1->major != version2->major)
return version1->major > version2->major ? 1 : -1;
if(version1->minor != version2->minor)
return version1->minor > version2->minor ? 1 : -1;
if(version1->patch != version2->patch)
return version1->patch > version2->patch ? 1 : -1;
return 0;
}
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty)
{
if(version->major > 0 || version->minor > 0 || version->patch > 0)
ffStrbufAppendF(pretty, "%u", version->major);
if(version->minor > 0 || version->patch > 0)
ffStrbufAppendF(pretty, ".%u", version->minor);
if(version->patch > 0)
ffStrbufAppendF(pretty, ".%u", version->patch);
}
static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, uint8_t prefixesLength, const char** prefixes)
{
long double size = (long double) bytes;
uint8_t counter = 0;
while(size > base && counter < prefixesLength - 1)
{
size /= base;
counter++;
}
if(counter == 0)
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
else if(counter < 3 || (counter == 3 && size < 100.0))
ffStrbufAppendF(result, "%.2Lf %s", size, prefixes[counter]);
else
ffStrbufAppendF(result, "%.0Lf %s", size, prefixes[counter]);
}
void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result)
{
if(binaryPrefix == FF_BINARY_PREFIX_TYPE_IEC)
parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB"});
else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_SI)
parseSize(result, bytes, 1000, 5, (const char*[]) {"B", "kB", "MB", "GB", "TB"});
else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_JEDEC)
parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KB", "MB", "GB", "TB"});
else
parseSize(result, bytes, 1024, 1, (const char*[]) {"B"});
}
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
{
if((ffStrbufIgnCaseComp(gtk2, gtk3) == 0) && (ffStrbufIgnCaseComp(gtk2, gtk4) == 0))
{
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK2/3/4]");
}
else if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
{
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK2/3], ");
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK4]");
}
else if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
{
ffStrbufAppend(buffer, gtk2);
ffStrbufAppendS(buffer, " [GTK2], ");
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK3/4]");
}
else
{
ffStrbufAppend(buffer, gtk2);
ffStrbufAppendS(buffer, " [GTK2], ");
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK3], ");
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK4]");
}
}
else if(gtk2->length > 0 && gtk3->length > 0)
{
if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
{
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK2/3]");
}
else
{
ffStrbufAppend(buffer, gtk2);
ffStrbufAppendS(buffer, " [GTK2], ");
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK3]");
}
}
else if(gtk3->length > 0 && gtk4->length > 0)
{
if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
{
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK3/4]");
}
else
{
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK3], ");
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK4]");
}
}
else if(gtk2->length > 0)
{
ffStrbufAppend(buffer, gtk2);
ffStrbufAppendS(buffer, " [GTK2]");
}
else if(gtk3->length > 0)
{
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK3]");
}
else if(gtk4->length > 0)
{
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK4]");
}
}
-26
View File
@@ -1,26 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_parsing_h
#define FF_INCLUDED_parsing_h
#include <stdint.h>
typedef struct FFVersion
{
uint32_t major;
uint32_t minor;
uint32_t patch;
} FFVersion;
#define FF_VERSION_INIT ((FFVersion) {0})
bool ffStrSet(const char* str);
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4);
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result);
#endif
-171
View File
@@ -1,171 +0,0 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "util/textModifier.h"
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
{
ffLogoPrintLine(instance);
//This is used by --set-keyless, in this case we wan't neither the module name nor the separator
if(moduleName == NULL)
return;
if(!instance->config.pipe)
{
fputs(FASTFETCH_TEXT_MODIFIER_RESET FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
ffPrintColor(&instance->config.colorKeys);
}
//NULL check is required for modules with custom keys, e.g. disk with the folder path
if(customKeyFormat == NULL || customKeyFormat->length == 0)
{
fputs(moduleName, stdout);
if(moduleIndex > 0)
printf(" %hhu", moduleIndex);
}
else
{
FFstrbuf key;
ffStrbufInit(&key);
ffParseFormatString(&key, customKeyFormat, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
});
ffPrintUserString(key.chars);
ffStrbufDestroy(&key);
}
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
ffStrbufWriteTo(&instance->config.separator, stdout);
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
}
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments)
{
FFstrbuf buffer;
ffStrbufInitA(&buffer, 256);
ffParseFormatString(&buffer, format, numArgs, arguments);
if(buffer.length > 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
ffPrintUserString(buffer.chars);
putchar('\n');
}
ffStrbufDestroy(&buffer);
}
void ffPrintFormat(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments)
{
ffPrintFormatString(instance, moduleName, moduleIndex, &moduleArgs->key, &moduleArgs->outputFormat, numArgs, arguments);
}
static void printError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, va_list arguments)
{
bool hasCustomErrorFormat = customErrorFormat != NULL && customErrorFormat->length > 0;
if(!hasCustomErrorFormat && !instance->config.showErrors)
return;
if(hasCustomErrorFormat)
{
FFstrbuf error;
ffStrbufInit(&error);
ffStrbufAppendVF(&error, message, arguments);
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, customErrorFormat, 1, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &error}
});
ffStrbufDestroy(&error);
}
else
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
vprintf(message, arguments);
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
putchar('\n');
}
}
void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...)
{
va_list arguments;
va_start(arguments, message);
printError(instance, moduleName, moduleIndex, customKeyFormat, customErrorFormat, message, arguments);
va_end(arguments);
}
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...)
{
va_list arguments;
va_start(arguments, message);
printError(instance, moduleName, moduleIndex, &moduleArgs->key, &moduleArgs->errorFormat, message, arguments);
va_end(arguments);
}
void ffPrintColor(const FFstrbuf* colorValue)
{
//If the color is not set, this would reset in \033[m, which resets everything.
//So we only print it, if the main color is at least one char.
if(colorValue->length == 0)
return;
fputs("\033[", stdout);
ffStrbufWriteTo(colorValue, stdout);
fputc('m', stdout);
}
void ffPrintCharTimes(char c, uint32_t times)
{
char str[32];
memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled
for(uint32_t i = sizeof(str); i <= times; i += sizeof(str))
fwrite(str, 1, sizeof(str), stdout);
uint32_t remaining = times % sizeof(str);
if(remaining > 0)
fwrite(str, 1, remaining, stdout);
}
void ffPrintUserString(const char* value)
{
while(*value != '\0')
{
if(*value != '\\')
{
putchar(*value);
++value;
continue;
}
++value;
if(*value == 'n')
putchar('\n');
else if(*value == 't')
putchar('\t');
else if(*value == 'e')
putchar('\e');
else if(*value == '\\')
putchar('\\');
else
{
putchar('\\');
putchar(*value);
}
++value;
}
}
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_printing
#define FF_INCLUDED_common_printing
#include "fastfetch.h"
#include "common/format.h"
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat);
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments);
void ffPrintFormat(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments);
FF_C_PRINTF(6, 7) void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...);
FF_C_PRINTF(5, 6) void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
void ffPrintColor(const FFstrbuf* colorValue);
void ffPrintCharTimes(char c, uint32_t times);
void ffPrintUserString(const char* str);
#endif
-10
View File
@@ -1,10 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_processing
#define FF_INCLUDED_common_processing
#include "util/FFstrbuf.h"
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
#endif
-38
View File
@@ -1,38 +0,0 @@
#include "fastfetch.h"
#include "common/processing.h"
#include "common/io.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
{
int pipes[2];
if(pipe(pipes) == -1)
return "pipe() failed";
pid_t childPid = fork();
if(childPid == -1)
return "fork() failed";
//Child
if(childPid == 0)
{
dup2(pipes[1], STDOUT_FILENO);
close(pipes[0]);
close(pipes[1]);
close(STDERR_FILENO);
execvp(argv[0], argv);
exit(901);
}
//Parent
close(pipes[1]);
waitpid(childPid, NULL, 0);
ffAppendFDBuffer(pipes[0], buffer);
close(pipes[0]);
return NULL;
}
-69
View File
@@ -1,69 +0,0 @@
#include "fastfetch.h"
#include "common/processing.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places.
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
{
SECURITY_ATTRIBUTES saAttr = {
.nLength = sizeof(SECURITY_ATTRIBUTES),
.lpSecurityDescriptor = NULL,
.bInheritHandle = TRUE,
};
HANDLE hChildStdoutRead, hChildStdoutWrite;
if (!CreatePipe(&hChildStdoutRead, &hChildStdoutWrite, &saAttr, 0))
return "CreatePipe() failed";
if (!SetHandleInformation(hChildStdoutRead, HANDLE_FLAG_INHERIT, 0))
return "SetHandleInformation(hChildStdoutRead) failed";
PROCESS_INFORMATION piProcInfo = {0};
STARTUPINFOA siStartInfo = {
.cb = sizeof(siStartInfo),
.dwFlags = STARTF_USESTDHANDLES,
.hStdOutput = hChildStdoutWrite,
};
BOOL success;
{
FF_STRBUF_AUTO_DESTROY cmdline;
ffStrbufInitF(&cmdline, "\"%s\"", argv[0]);
for(char* const* parg = &argv[1]; *parg; ++parg)
{
ffStrbufAppendC(&cmdline, ' ');
ffStrbufAppendS(&cmdline, *parg);
}
success = CreateProcessA(
NULL, // application name
cmdline.chars, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo // receives PROCESS_INFORMATION
);
}
CloseHandle(hChildStdoutWrite);
if(!success)
{
CloseHandle(hChildStdoutRead);
return "CreateProcessA() failed";
}
char str[1024];
DWORD nRead;
while(ReadFile(hChildStdoutRead, str, sizeof(str), &nRead, NULL) && nRead > 0)
ffStrbufAppendNS(buffer, nRead, str);
CloseHandle(hChildStdoutRead);
return NULL;
}
-210
View File
@@ -1,210 +0,0 @@
#include "fastfetch.h"
#include "common/properties.h"
#include <stdlib.h>
#ifdef _WIN32
#include "util/windows/getline.h"
#endif
static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer)
{
if(**line == '\0')
return false;
//Skip any amount of whitespace at the begin of line
while(**line == ' ' || **line == '\t')
++(*line);
while(*start != '\0')
{
// Any amount of whitespace in the format string matches any amount of whitespace in the line, even none
if(*start == ' ' || *start == '\t')
{
while(*start == ' ' || *start == '\t')
++start;
while(**line == ' ' || **line == '\t')
++(*line);
continue;
}
//Line doesn't match start, skip it
if(**line != *start || **line == '\0')
return false;
//Line and start match, continue testing
++(*line);
++start;
}
char valueEnd = '\n';
//Allow faster parsing of XML
if(*(*line - 1) == '>')
valueEnd = '<';
//Skip any amount of whitespace at the begin of the value
while(**line == ' ' || **line == '\t')
++(*line);
//Allow faster parsing of quotet values
if(**line == '"' || **line == '\'')
{
valueEnd = **line;
++(*line);
}
//Copy the value to the buffer
while(**line != valueEnd && **line != '\n' && **line != '\0')
{
ffStrbufAppendC(buffer, **line);
++(*line);
}
ffStrbufTrimRight(buffer, ' ');
return true;
}
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer)
{
return parsePropLinePointer(&line, start, buffer);
}
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
{
while(!parsePropLinePointer(&lines, start, buffer))
{
while(*lines != '\0' && *lines != '\n')
++lines;
if(*lines == '\0')
return false;
//Skip '\n'
++lines;
}
return true;
}
// The following functions return true if the file was found, independently if start was found
// Buffers which already contain content are not overwritten
// The last occurence of start in the first file will be the one used
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
{
FILE* file = fopen(filename, "r");
if(file == NULL)
return false;
bool valueStorage[4];
bool* unsetValues;
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++)
{
if((unsetValues[i] = queries[i].buffer->length == 0))
allSet = false;
}
if(allSet)
goto done;
char* line = NULL;
size_t len = 0;
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;
}
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
}
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
FFstrbuf absolutePath;
ffStrbufInitA(&absolutePath, 64);
ffStrbufAppendS(&absolutePath, instance->state.passwd->pw_dir);
ffStrbufAppendC(&absolutePath, '/');
ffStrbufAppendS(&absolutePath, relativeFile);
bool result = ffParsePropFileValues(absolutePath.chars, numQueries, queries);
ffStrbufDestroy(&absolutePath);
return result;
}
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
bool foundAFile = false;
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
{
//We need to copy the config dir each time, because it used by multiple threads, so we can't directly write to it.
ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
ffStrbufAppendS(&baseDir, relativeFile);
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
foundAFile = true;
bool allSet = true;
for(uint32_t k = 0; k < numQueries; k++)
{
if(queries[k].buffer->length == 0)
{
allSet = false;
break;
}
}
if(allSet)
break;
}
ffStrbufDestroy(&baseDir);
return foundAFile;
}
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
-23
View File
@@ -1,23 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_properties
#define FF_INCLUDED_common_properties
#include "fastfetch.h"
typedef struct FFpropquery
{
const char* start;
FFstrbuf* buffer;
} FFpropquery;
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer);
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer);
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer);
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
#endif
-359
View File
@@ -1,359 +0,0 @@
#include "fastfetch.h"
#include "common/settings.h"
#include "common/library.h"
#include "common/thread.h"
#include "common/io.h"
#include <string.h>
typedef enum FFInitState
{
FF_INITSTATE_UNINITIALIZED = 0,
FF_INITSTATE_SUCCESSFUL = 1,
FF_INITSTATE_FAILED = 2
} FFInitState;
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
static dataObject data; \
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
ffThreadMutexLock(&mutex); \
if(initState != FF_INITSTATE_UNINITIALIZED) {\
ffThreadMutexUnlock(&mutex); \
return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \
} \
initState = FF_INITSTATE_SUCCESSFUL; \
void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \
if(libraryHandle == NULL) { \
initState = FF_INITSTATE_FAILED; \
ffThreadMutexUnlock(&mutex); \
return NULL; \
} \
#define FF_LIBRARY_DATA_LOAD_SYMBOL(symbolName) \
data.ff ## symbolName = dlsym(libraryHandle, #symbolName); \
if(data.ff ## symbolName == NULL) { \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
ffThreadMutexUnlock(&mutex); \
return NULL; \
}
#define FF_LIBRARY_DATA_LOAD_RETURN \
initState = FF_INITSTATE_SUCCESSFUL; \
ffThreadMutexUnlock(&mutex); \
return &data;
#define FF_LIBRARY_DATA_LOAD_ERROR \
{ \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
ffThreadMutexUnlock(&mutex); \
return NULL; \
}
#ifdef FF_HAVE_GIO
#include <gio/gio.h>
typedef struct GVariantGetters
{
FF_LIBRARY_SYMBOL(g_variant_get_string)
FF_LIBRARY_SYMBOL(g_variant_get_boolean)
FF_LIBRARY_SYMBOL(g_variant_get_int32)
} GVariantGetters;
static FFvariant getGVariantValue(GVariant* variant, FFvarianttype type, const GVariantGetters* variantGetters)
{
if(variant == NULL)
return FF_VARIANT_NULL;
else if(type == FF_VARIANT_TYPE_STRING)
return (FFvariant) {.strValue = variantGetters->ffg_variant_get_string(variant, NULL)};
else if(type == FF_VARIANT_TYPE_BOOL)
return (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true};
else if(type == FF_VARIANT_TYPE_INT)
return (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)};
else
return FF_VARIANT_NULL;
}
typedef struct GSettingsData
{
FF_LIBRARY_SYMBOL(g_settings_schema_source_lookup)
FF_LIBRARY_SYMBOL(g_settings_schema_has_key)
FF_LIBRARY_SYMBOL(g_settings_new_full)
FF_LIBRARY_SYMBOL(g_settings_get_value)
FF_LIBRARY_SYMBOL(g_settings_get_user_value)
FF_LIBRARY_SYMBOL(g_settings_get_default_value)
FF_LIBRARY_SYMBOL(g_settings_schema_source_get_default)
GSettingsSchemaSource* schemaSource;
GVariantGetters variantGetters;
} GSettingsData;
static const GSettingsData* getGSettingsData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_lookup)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_has_key)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_new_full)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_get_value)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_get_user_value)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_get_default_value)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_get_default)
#define data data.variantGetters
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
#undef data
data.schemaSource = data.ffg_settings_schema_source_get_default();
if(data.schemaSource == NULL)
FF_LIBRARY_DATA_LOAD_ERROR
FF_LIBRARY_DATA_LOAD_RETURN
}
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
{
const GSettingsData* data = getGSettingsData(instance);
if(data == NULL)
return FF_VARIANT_NULL;
GSettingsSchema* schema = data->ffg_settings_schema_source_lookup(data->schemaSource, schemaName, true);
if(schema == NULL)
return FF_VARIANT_NULL;
if(data->ffg_settings_schema_has_key(schema, key) == false)
return FF_VARIANT_NULL;
GSettings* settings = data->ffg_settings_new_full(schema, NULL, path);
if(settings == NULL)
return FF_VARIANT_NULL;
GVariant* variant = data->ffg_settings_get_value(settings, key);
if(variant != NULL)
return getGVariantValue(variant, type, &data->variantGetters);
variant = data->ffg_settings_get_user_value(settings, key);
if(variant != NULL)
return getGVariantValue(variant, type, &data->variantGetters);
variant = data->ffg_settings_get_default_value(settings, key);
return getGVariantValue(variant, type, &data->variantGetters);
}
#else //FF_HAVE_GIO
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
{
FF_UNUSED(instance, schemaName, path, key, type)
return FF_VARIANT_NULL;
}
#endif //FF_HAVE_GIO
#ifdef FF_HAVE_DCONF
#include <dconf.h>
typedef struct DConfData
{
FF_LIBRARY_SYMBOL(dconf_client_read_full)
FF_LIBRARY_SYMBOL(dconf_client_new)
GVariantGetters variantGetters;
DConfClient* client;
} DConfData;
static const DConfData* getDConfData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_read_full)
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
#define data data.variantGetters
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
#undef data
data.client = data.ffdconf_client_new();
if(data.client == NULL)
FF_LIBRARY_DATA_LOAD_ERROR
FF_LIBRARY_DATA_LOAD_RETURN
}
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type)
{
const DConfData* data = getDConfData(instance);
if(data == NULL)
return FF_VARIANT_NULL;
GVariant* variant = data->ffdconf_client_read_full(data->client, key, DCONF_READ_FLAGS_NONE, NULL);
if(variant != NULL)
return getGVariantValue(variant, type, &data->variantGetters);
variant = data->ffdconf_client_read_full(data->client, key, DCONF_READ_USER_VALUE, NULL);
if(variant != NULL)
return getGVariantValue(variant, type, &data->variantGetters);
variant = data->ffdconf_client_read_full(data->client, key, DCONF_READ_DEFAULT_VALUE, NULL);
return getGVariantValue(variant, type, &data->variantGetters);
}
#else //FF_HAVE_DCONF
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type)
{
FF_UNUSED(instance, key, type)
return FF_VARIANT_NULL;
}
#endif //FF_HAVE_DCONF
FFvariant ffSettingsGet(const FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type)
{
FFvariant gsettings = ffSettingsGetGSettings(instance, gsettingsSchemaName, gsettingsPath, gsettingsKey, type);
if(
(type == FF_VARIANT_TYPE_BOOL && gsettings.boolValueSet) ||
(type != FF_VARIANT_TYPE_BOOL && gsettings.strValue != NULL)
) return gsettings;
return ffSettingsGetDConf(instance, dconfKey, type);
}
#ifdef FF_HAVE_XFCONF
#include <xfconf/xfconf.h>
typedef struct XFConfData
{
FF_LIBRARY_SYMBOL(xfconf_channel_get)
FF_LIBRARY_SYMBOL(xfconf_channel_has_property)
FF_LIBRARY_SYMBOL(xfconf_channel_get_string)
FF_LIBRARY_SYMBOL(xfconf_channel_get_bool)
FF_LIBRARY_SYMBOL(xfconf_channel_get_int)
FF_LIBRARY_SYMBOL(xfconf_init)
} XFConfData;
static const XFConfData* getXFConfData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_has_property)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get_bool)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get_int)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_init)
if(data.ffxfconf_init(NULL) == false)
FF_LIBRARY_DATA_LOAD_ERROR
FF_LIBRARY_DATA_LOAD_RETURN
}
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
{
const XFConfData* data = getXFConfData(instance);
if(data == NULL)
return FF_VARIANT_NULL;
XfconfChannel* channel = data->ffxfconf_channel_get(channelName); // Never fails according to documentation but rather returns an empty channel
if(!data->ffxfconf_channel_has_property(channel, propertyName))
return FF_VARIANT_NULL;
if(type == FF_VARIANT_TYPE_INT)
return (FFvariant) {.intValue = data->ffxfconf_channel_get_int(channel, propertyName, 0)};
if(type == FF_VARIANT_TYPE_STRING)
return (FFvariant) {.strValue = data->ffxfconf_channel_get_string(channel, propertyName, NULL)};
if(type == FF_VARIANT_TYPE_BOOL)
return (FFvariant) {.boolValue = data->ffxfconf_channel_get_bool(channel, propertyName, false), .boolValueSet = true};
return FF_VARIANT_NULL;
}
#else //FF_HAVE_XFCONF
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
{
FF_UNUSED(instance, channelName, propertyName, type)
return FF_VARIANT_NULL;
}
#endif //FF_HAVE_XFCONF
#ifdef FF_HAVE_SQLITE3
#include <sqlite3.h>
typedef struct SQLiteData
{
FF_LIBRARY_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_SYMBOL(sqlite3_prepare_v2)
FF_LIBRARY_SYMBOL(sqlite3_step)
FF_LIBRARY_SYMBOL(sqlite3_data_count)
FF_LIBRARY_SYMBOL(sqlite3_column_int)
FF_LIBRARY_SYMBOL(sqlite3_finalize)
FF_LIBRARY_SYMBOL(sqlite3_close)
} SQLiteData;
static const SQLiteData* getSQLiteData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_step)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_data_count)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_int)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_finalize)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_close)
FF_LIBRARY_DATA_LOAD_RETURN
}
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
{
if(!ffFileExists(dbPath, S_IFREG))
return 0;
const SQLiteData* data = getSQLiteData(instance);
if(data == NULL)
return 0;
sqlite3* db;
if(data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
return 0;
sqlite3_stmt* stmt;
if(data->ffsqlite3_prepare_v2(db, query, (int) strlen(query), &stmt, NULL) != SQLITE_OK)
{
data->ffsqlite3_close(db);
return 0;
}
if(data->ffsqlite3_step(stmt) != SQLITE_ROW || data->ffsqlite3_data_count(stmt) < 1)
{
data->ffsqlite3_finalize(stmt);
data->ffsqlite3_close(db);
return 0;
}
int result = data->ffsqlite3_column_int(stmt, 0);
data->ffsqlite3_finalize(stmt);
data->ffsqlite3_close(db);
return result;
}
#else //FF_HAVE_SQLITE3
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
{
FF_UNUSED(instance, dbPath, query)
return 0;
}
#endif //FF_HAVE_SQLITE3
#ifdef __ANDROID__
#include <sys/system_properties.h>
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
ffStrbufEnsureFree(result, PROP_VALUE_MAX);
result->length += (uint32_t) __system_property_get(propName, result->chars + result->length);
result->chars[result->length] = '\0';
}
#endif //__ANDROID__
-39
View File
@@ -1,39 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_settings
#define FF_INCLUDED_common_settings
#include "fastfetch.h"
typedef enum FFvarianttype
{
FF_VARIANT_TYPE_STRING,
FF_VARIANT_TYPE_BOOL,
FF_VARIANT_TYPE_INT
} FFvarianttype;
typedef union FFvariant
{
const char* strValue;
int32_t intValue;
struct
{
bool boolValueSet;
bool boolValue;
};
} FFvariant;
#define FF_VARIANT_NULL ((FFvariant){.strValue = NULL})
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type);
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type);
FFvariant ffSettingsGet(const FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type);
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
#ifdef __ANDROID__
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
#endif
#endif
-55
View File
@@ -1,55 +0,0 @@
#include "sysctl.h"
#include <stdlib.h>
const char* ffSysctlGetString(const char* propName, FFstrbuf* result)
{
size_t neededLength;
if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator
return "sysctlbyname() failed";
ffStrbufEnsureFree(result, (uint32_t) neededLength - 1);
if(sysctlbyname(propName, result->chars + result->length, &neededLength, NULL, 0) == 0)
result->length += (uint32_t) neededLength - 1;
result->chars[result->length] = '\0';
return NULL;
}
int ffSysctlGetInt(const char* propName, int defaultValue)
{
int result;
size_t neededLength = sizeof(result);
if(sysctlbyname(propName, &result, &neededLength, NULL, 0) != 0)
return defaultValue;
return result;
}
int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue)
{
int64_t result;
size_t neededLength = sizeof(result);
if(sysctlbyname(propName, &result, &neededLength, NULL, 0) != 0)
return defaultValue;
return result;
}
void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength)
{
if(sysctl(request, requestLength, NULL, resultLength, NULL, 0) != 0)
return NULL;
void* data = malloc(*resultLength);
if(data == NULL)
return NULL;
if(sysctl(request, requestLength, data, resultLength, NULL, 0) != 0)
{
free(data);
return NULL;
}
return data;
}
-17
View File
@@ -1,17 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_sysctl
#define FF_INCLUDED_common_sysctl
#include "fastfetch.h"
#include "util/FFcheckmacros.h"
#include <sys/types.h>
#include <sys/sysctl.h>
const char* ffSysctlGetString(const char* propName, FFstrbuf* result);
FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue);
FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue);
FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength);
#endif
-48
View File
@@ -1,48 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_thread
#define FF_INCLUDED_common_thread
#include "fastfetch.h"
#ifdef FF_HAVE_THREADS
#if defined(_WIN32)
#include <handleapi.h>
#include <synchapi.h>
#include <process.h>
#define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT
typedef SRWLOCK FFThreadMutex;
typedef HANDLE FFThreadType;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { AcquireSRWLockExclusive(mutex); }
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { ReleaseSRWLockExclusive(mutex); }
static inline FFThreadType ffThreadCreate(unsigned (__stdcall* func)(void*), void* data) {
return (FFThreadType)_beginthreadex(NULL, 0, func, data, 0, NULL);
}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; }
static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); }
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, INFINITE); }
#else
#include <pthread.h>
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t FFThreadMutex;
typedef pthread_t FFThreadType;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); }
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); }
static inline FFThreadType ffThreadCreate(void* (* func)(void*), void* data) {
FFThreadType newThread = 0;
pthread_create(&newThread, NULL, func, data);
return newThread;
}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; }
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
static inline void ffThreadJoin(FFThreadType thread) { pthread_join(thread, NULL); }
#endif
#else //FF_HAVE_THREADS
#define FF_THREAD_MUTEX_INITIALIZER 0
typedef char FFThreadMutex;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { FF_UNUSED(mutex) }
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { FF_UNUSED(mutex) }
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType)
#endif //FF_HAVE_THREADS
#endif
-38
View File
@@ -1,38 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_time
#define FF_INCLUDED_common_time
#include <stdint.h>
#ifdef _WIN32
#include <synchapi.h>
#include <profileapi.h>
#else
#include <time.h>
#endif
static inline uint64_t ffTimeGetTick() //In msec
{
#ifdef _WIN32
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
LARGE_INTEGER start;
QueryPerformanceCounter(&start);
return (uint64_t)(start.QuadPart * 1000 / frequency.QuadPart);
#else
struct timespec timeNow;
clock_gettime(CLOCK_MONOTONIC, &timeNow);
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000));
#endif
}
static inline void ffTimeSleep(uint32_t msec)
{
#ifdef _WIN32
SleepEx(msec, TRUE);
#else
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
#endif
}
#endif
-16
View File
@@ -1,16 +0,0 @@
# Fastfetch system configuration
# This file sets the default config for all users of the system.
# For more information about how configuration files work,
# see ~/.config/fastfetch/config.conf, generated during first run.
# All options that can be put there (or passed as argument) can be put here too.
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf
# to overwrite this file with the current default file.
# User config option
# Sets if fastfetch should load user provided configuration.
# If this is off, fastfetch ignores the user config file and any passed arguments
# Must be true or false
# Default is true.
#--load-user-config true
-367
View File
@@ -1,367 +0,0 @@
# Fastfetch configuration
# Write every argument in different lines.
# Direct arguments will overwrite the corresponding ones in this file.
# Argument keys are not case sensitive.
# Whitespaces are trimmed at the beginning and the end.
# Empty lines or lines starting with # are ignored.
# This file was shipped with $" FASTFETCH_PROJECT_VERSION $".
# Use fastfetch --print-config-user > ~/.config/fastfetch/config.conf to overwrite this file with the current defaults
# Below some often usefull options are listed. Uncomment and modify them so they take affect.
# Note that there are a lot more options than the ones listed here, take a look at "fastfetch --help".
# Of course all of them can be made persistent here too.
# Config option:
# Load additional config files.
# Some are shipped with fastfetch, list them with "fastfetch --list-presets".
# Must be a path to a config file or the name of a shipped preset.
# The config file is completly loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones.
# Can be used multiple times to load multiple config files / presets.
#--load-config /path/to/config.txt
# Structure option:
# Sets the modules to use and their order.
# Must be a list of module names, separated by colons.
# List available modules with "fastfetch --list-modules".
# Get the default structure with "fastfetch --print-structure".
#--structure $" FASTFETCH_DATATEXT_STRUCTURE $"
# Multithreading option:
# Sets if fastfetch should use multiple threads to detect the values.
# Must be true or false.
# Default is true.
#--multithreading true
# Print stat option:
# Sets if fastfetch should print time usage (in ms) for individual modules
# If true, it will also enable --show-errors
# Must be true or false.
# Default is false.
#--stat true
# Slow operations option:
# Sets if fastfetch is allowed to use known slow operations to detect more / better values.
# Must be true or false.
# Default is false.
#--allow-slow-operations false
# Linewrap option:
# Sets if fastfetch should disable linewrap during the run.
# Must be true or false.
# Default is true.
#--disable-linewrap true
# Cursor option:
# Sets if fastfetch should hide the console cursor during the run.
# Must be true or false.
# Default is true.
#--hide-cursor true
# Logo option:
# Sets the logo to use.
# List available logos with "fastfetch --list-logos".
# Print available logos with "fastfetch --print-logos".
# Must be the name of an available logo or a path to a text file containing a custom logo.
# Default is the current distribution.
#--logo arch
# Logo type option:
# Sets the logo type to use.
# Must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty or chafa.
# Default is auto.
#--logo-type auto
# Logo width option:
# Sets the width of the logo (in characters) if the logo is an image.
# Must be a positive integer.
# Default is 65.
#--logo-width 65
# Logo height option:
# Sets the height of the logo (in characters) if the logo is an image.
# Must be a positive integer.
# Default is 0 (keeps aspect ration).
#--logo-height 0
# Logo color options:
# Overwrite a color in the logo. Also works for user provided logos.
# In the user logo, they replace $[1-9]. Use $$ to print a single $ sign.
# Must be linux console color codes or the name of a color.
# Default is the one specified by the logo.
# Use "fastfetch --help color" to learn more and see examples.
# Valid index range is [1-9].
#--logo-color-1 red
#--logo-color-2 32
# [...]
#--logo-color-9 yellow
# Logo padding option:
# Adds a padding to the left and the right side of the logo.
# Must be a positive integer.
# Default is 0.
#--logo-padding 0
# Logo padding left option:
# Adds a padding to the left side of the logo.
# Must be a positive integer.
# Default is 0.
#--logo-padding-left 0
# Logo padding right option:
# Adds a padding to the right side of the logo.
# Must be a positive integer.
# Default is 0.
#--logo-padding-right 0
# Logo print remaining option:
# Sets if the remaining logo should be printed, it is has more lines than modules to show.
# Must be true or false.
# Default is true.
#--logo-print-remaining true
# Color keys option:
# Sets the color of the keys.
# Must be linux console color codes or the name of a color.
# Default is the key color of the logo.
# Use "fastfetch --help color" to learn more and see examples.
#--color-keys magenta
# Color title option:
# Sets the color of the title.
# Must be linux console color codes or the name of a color.
# Default is the title color of the logo.
# Use "fastfetch --help color" to learn more and see examples.
#--color-title magenta
# Binary prefix option:
# Sets the binary prefix to use.
# Must be a IEC, SI or JEDEC.
# Default is IEC.
#--binary-prefix IEC
# Title FQDN option:
# Sets if the title should use the fully qualified domain name.
# Must be true or false.
# Default is false.
#--title-fqdn false
# Separator option:
# Sets the string placed between a key and its value.
# Can be any string.
# Default is ": ".
#--separator ": "
# Separator string option:
# Sets the string printed by the "separator" module (usually between title and rest of output)
# Must be any string. It is repated / cut to fit perfectly.
# Default is "-"
#--separator-string -
# Public IP URL option:
# Sets the URL of public IP detection server to be used.
# Only HTTP protocol is supported, and the value should not contain "http://" prefix.
# Default is "ipinfo.io/ip".
#--public-ip-url "ipinfo.io/ip"
# Public IP timeout option:
# Sets the time to wait for the public ip server to respond.
# Must be a positive integer.
# Default is 0 (disabled).
#--public-ip-timeout 0
# Weather output format option:
# Sets the weather format to be used. It must be URI encoded.
# See: https://github.com/chubin/wttr.in#one-line-output
# Default is "%t+-+%C+(%l)".
#--weather-output-format "%t+-+%C+(%l)"
# Weather timeout option:
# Sets the time to wait for the weather server (wttr.in) to respond.
# Must be a positive integer.
# Default is 0 (disabled).
#--weather-timeout 0
# OS file option
# Sets the path to the file containing the operating system information.
# Should be a valid path to an existing file.
# Default is /etc/os-release.
#--os-file /etc/os-release
# Player name option
# Sets the name of the player. This is also used in song detection
# Must be the exact name of the player or a dbus address (e.g. org.mpris.MediaPlayer2.spotify)
# Default is the first match starting with org.mpris.MediaPlayer2.
#--player-name spotify
# Escape bedrock option
# Sets if fastfetch should escape the bedrock jail, if it detectes that it is running in one
# Must be true or false.
# Default is true.
#--escape-bedrock true
# GL option
# Sets with opengl context creation library to use
# Must be either auto, egl, glx or osmesa
# Default is auto.
#--gl auto
# Percentage output type option
# Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported.
# Only works with default format ( without --module-format option ).
# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar
#--percent-type 1
# Key options:
# Sets the displayed key of a module
# Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help.
#--os-key OS
#--host-key Host
#--chassis-key Chassis
#--kernel-key Kernel
#--uptime-key Uptime
#--processes-key Processes
#--packages-key Packages
#--shell-key Shell
#--resolution-key Resolution {1}
#--de-key DE
#--wm-key WM
#--wm-theme-key WM Theme
#--theme-key Theme
#--icons-key Icons
#--font-key Font
#--cursor-key Cursor
#--terminal-key Terminal
#--terminal-font-key Terminal Font
#--cpu-key CPU
#--cpu-usage-key CPU Usage
#--gpu-key GPU {1}
#--memory-key Memory
#--swap-key Swap
#--disk-key Disk ({1})
#--battery-key Battery {1}
#--poweradapter-key Power Adapter {1}
#--locale-key Locale
#--local-ip-key Local IP ({1})
#--public-ip-key Public IP
#--wifi-key Wifi
#--weather-key Weather
#--player-key Media Player
#--media-key Media
#--datetime-key Date Time
#--vulkan-key Vulkan
#--opengl-key OpenGL
#--opencl-key OpenCL
#--users-key Users
# Format options:
# Sets the format string for module values.
# For information on format strings, see "fastfetch --help format".
# To see the parameter they take and their default value, see "fastfetch --help *-format", e.g. "fastfetch --help os-format".
# An empty format string (As they are currently below) will behave as if it was not set.
#--os-format
#--host-format
#--chassis-format
#--kernel-format
#--uptime-format
#--processes-format
#--packages-format
#--shell-format
#--resolution-format
#--de-format
#--wm-format
#--wm-theme-format
#--theme-format
#--icons-format
#--font-format
#--cursor-format
#--terminal-format
#--terminal-font-format
#--cpu-format
#--cpu-usage-format
#--gpu-format
#--memory-format
#--swap-format
#--disk-format
#--battery-format
#--poweradapter-format
#--locale-format
#--local-ip-format
#--public-ip-format
#--weather-format
#--player-format
#--media-format
#--datetime-format
#--vulkan-format
#--opengl-format
#--opencl-format
#--users-format
# Error options:
# Sets the format string to use if an error occured
# For information on format strings, see "fastfetch --help format".
# Each of them take the error as first and only argument.
# If one of them is set, the module will appear, even if --show-errors is not given.
#--os-error
#--host-error
#--chassis-error
#--kernel-error
#--uptime-error
#--processes-error
#--packages-error
#--shell-error
#--resolution-error
#--de-error
#--wm-error
#--wm-theme-error
#--theme-error
#--icons-error
#--font-error
#--cursor-error
#--terminal-error
#--terminal-font-error
#--cpu-error
#--cpu-usage-error
#--gpu-error
#--memory-error
#--swap-error
#--disk-error
#--battery-error
#--poweradapter-error
#--locale-error
#--local-ip-error
#--public-ip-error
#--weather-error
#--player-error
#--media-error
#--datetime-error
#--vulkan-error
#--opengl-error
#--opencl-error
#--users-error
# Library options:
# Sets an user specific path to a library to load.
# Must be a valid path to a library.
#--lib-PCI /usr/lib/libpci.so
#--lib-vulkan /usr/lib/libvulkan.so (libMoltenVK.dylib on macOS)
#--lib-wayland /usr/lib/libwayland-client.so
#--lib-xcb-randr /usr/lib/libxcb-randr.so
#--lib-xcb /usr/lib/libxcb.so
#--lib-Xrandr /usr/lib/libXrandr.so
#--lib-X11 /usr/lib/libX11.so
#--lib-gio /usr/lib/libgio-2.0.so
#--lib-DConf /usr/lib/libdconf.so
#--lib-DBus /usr/lib/libdbus-1.so
#--lib-XFConf /usr/lib/libxfconf-0.so
#--lib-sqlite3 /usr/lib/libsqlite3.so
#--lib-rpm /usr/lib/librpm.so
#--lib-imagemagick /usr/lib/libMagickCore-7.Q16HDRI.so
#--lib-z /usr/lib/libz.so
#--lib-chafa /usr/lib/libchafa.so
#--lib-egl /usr/lib/libEGL.so
#--lib-glx /usr/lib/libGLX.so
#--lib-osmesa /usr/lib/libOSMesa.so
#--lib-opencl /usr/lib/libOpenCL.so
#--lib-cjson /usr/lib/libcjson.so
#--lib-freetype /data/data/com.termux/files/usr/lib
-123
View File
@@ -1,123 +0,0 @@
Usage: fastfetch <options>
Informative options:
-h,--help: Show this message
-h,--help <command>: Show help for a specific command
-v,--version: Show the version of fastfetch
--list-logos: List available logos
--list-modules: List available modules
--list-presets: List presets fastfetch knows about; they can be loaded with --load-config (+)
--list-features: List the supported features fastfetch was compiled with (mainly for development)
--print-logos: Print available logos
--print-config-system: Print the default system config
--print-config-user: Print the default user config
--print-structure: Print the default structure
General options:
--load-config <file>: Load a config file or preset (+)
--multithreading <?value>: Use multiple threads to detect values
--stat <?value>: Show time usage (in ms) for individual modules
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
--pipe <?value>: Disable logo and all escape sequences
Logo options:
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-preserve-aspect-radio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
--logo-color-[1-9] <color>: Overwrite a color in the logo
--logo-padding <padding>: Set the padding on the left and the right of the logo
--logo-padding-left <padding>: Set the padding on the left of the logo
--logo-padding-right <padding>: Set the padding on the right of the logo
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
--file <file>: Short for --logo-type file --logo <file>
--file-raw <file>: Short for --logo-type file-raw --logo <file>
--data <data>: Short for --logo-type data --logo <data>
--data-raw <data>: Short for --logo-type data-raw --logo <data>
--sixel <file>: Short for --logo-type sixel --logo <file>
--kitty <file>: Short for --logo-type kitty --logo <file>
--iterm <file>: Short for --logo-type iterm --logo <file>
--chafa <file>: Short for --logo-type chafa --logo <file>
--chafa-fg-only <?value>: Produce character-cell output using foreground colors only. See chafa document for detail
--chafa-symbols <str>: Specify character symbols to employ in final output. See chafa document for detail
--chafa-canvas-mode <value>: Determine how colors are used in the output. This value maps the int value of enum ChafaCanvasMode. See chafa document for detail
--chafa-color-space <value>: Set color space used for quantization. 0 for RGB; 1 for DIN99d. See chafa document for detail
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
Display options:
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
--color-keys <color>: Set the color of the keys
--color-title <color>: Set the color of the title
-c,--color <color>: Set the color of both the keys and title
--separator <str>: Set the separator between key and value. Default is a colon with a space
--set <key=value>: Hard set the value of a key
--set-keyless <key=value>: Hard set the value of a key, but don't print the key or the separator
--show-errors <?value>: Print occurring errors
--disable-linewrap <?value>: Whether to disable line wrap during the run
--hide-cursor <?value>: Whether to hide the cursor during the run
--binary-prefix <value>: Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC.
General module options:
--<module>-format <format>: Set the format string to use for each specific module.
To see how a format string works, use fastfetch --help format.
To see help about a specific format string, use fastfetch --help <module>-format.
--<module>-key <key>: Set the key to use for each specific module.
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
--<module>-error <format>: Set the error format string to use for each specific module.
The error is given as the first and only argument.
Setting this for a module will cause it to appear, even if --show-errors is not given.
Library options: Set the path of a library to load
--lib-PCI <path>
--lib-vulkan <path>
--lib-wayland <path>
--lib-xcb-randr <path>
--lib-xcb <path>
--lib-Xrandr <path>
--lib-X11 <path>
--lib-gio <path>
--lib-DConf <path>
--lib-DBus <path>
--lib-XFConf <path>
--lib-sqlite3 <path>
--lib-rpm <path>
--lib-imagemagick <path>
--lib-z <path>
--lib-chafa <path>
--lib-egl <path>
--lib-glx <path>
--lib-osmesa <path>
--lib-opencl <path>
--lib-cjson <path>
Module specific options:
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
--separator-string <str>: Set the string printed by the separator module
--os-file <path>: Set the path to the file containing OS information
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--public-ip-url: The URL of public IP detection server to be used.
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
--weather-output-format: The output weather format to be used. It must be URI encoded.
--player-name: The name of the player to use
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both. Default is 1
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
If a value starts with a ?, it is optional. "true" will be used if not set.
A (+) at the end indicates that more help can be printed with --help <option>
All options can be made permanent in $XDG_CONFIG_HOME/fastfetch/config.conf
-9
View File
@@ -1,9 +0,0 @@
usage: fastfetch --color <color>
<color> must be a color encoding for linux terminals. 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 pink
--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.
-9
View File
@@ -1,9 +0,0 @@
usage: fastfetch --load-config <file>
Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.
If the file is relative it looks in the following order:
- relative to the current working directory
- relative to ~/.local/share/fastfetch/presets/
- relative to /usr/share/fastfetch/presets/
Fastfetch provides some default presets. List them with --print-available-presets.
Note that this will only print presets fastfetch knows about and not every possible one.
-36
View File
@@ -1,36 +0,0 @@
A format string is a string that contains placeholders for values.
These placeholders begin with a '{', containing the index of the value, and end with a '}'.
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce
The format string can contain placeholders in any order and have multiple occurences.
To include spaces when setting from the command line, surround the whole string with double quotes (").
If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second v
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces aro
If the last placeholder isn't closed, it will be treated like it was at the end of the format string.
To only print something if a variable is set, use "{?<index>} ... {?}".
For example, to only print a second value if it is set, use "{?2} Second value: {2}{?}".
If a "{?}" is found without an opener, it is printed as is.
To only print something if a variable is not set, do the same as with if, just replace every '?' with a '!'.
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}"
To stop formatting at any point in the format string, use "{-}".
To print something with color, start a placeholder with a '#' and then the linux terminal color encoding.
"\\033[" at the start, and an 'm' at the end is automatically added, so don't do that.
A "{#}" is equivalent to a "{#0}" and resets everything to normal.
For example to print something pink and underline, use "{#4;35}...{#}".
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Sele
Which escape codes are supported and how they look is defined by your terminal.
If a format string evaluates to an empty value, the whole line in the output will be discarded.
You can therefore use --host-format " " to disable host output.
Note that --host-format "" would evaluate as not set, and therefore use the built-in host format
Format string is also the way to go to set a fixed value - just use one without placeholders.
For example when running in headless mode, you could use "--resolution-format "Preferred".
-44
View File
@@ -1,44 +0,0 @@
Battery
Bios
Board
Break
Chassis
Colors
CPU
CPUUsage
Cursor
Date
Datetime
DE
Disk
Font
GPU
Host
Icons
Kernel
Locale
LocalIP
Media
Memory
OpenGL
OS
Packages
Player
PowerAdapter
Processes
PublicIP
Resolution
Separator
Shell
Swap
Terminal
TerminalFont
Theme
Time
Title
Uptime
Vulkan
Weather
Wifi
WM
WMTheme
-1
View File
@@ -1 +0,0 @@
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
-22
View File
@@ -1,22 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_battery_battery
#define FF_INCLUDED_detection_battery_battery
#include "fastfetch.h"
#define FF_BATTERY_TEMP_UNSET (0/0.0)
typedef struct BatteryResult
{
FFstrbuf manufacturer;
FFstrbuf modelName;
FFstrbuf technology;
double capacity;
FFstrbuf status;
double temperature;
} BatteryResult;
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results);
#endif
-108
View File
@@ -1,108 +0,0 @@
#include "fastfetch.h"
#include "battery.h"
#include "util/apple/cf_helpers.h"
#include "detection/temps/temps_apple.h"
#include <IOKit/IOKitLib.h>
static double detectBatteryTemp()
{
FF_LIST_AUTO_DESTROY temps;
ffListInit(&temps, sizeof(FFTempValue));
ffDetectCoreTemps(FF_TEMP_BATTERY, &temps);
if(temps.length == 0)
return FF_BATTERY_TEMP_UNSET;
double result = 0;
for(uint32_t i = 0; i < temps.length; ++i)
{
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
result += tempValue->value;
//TODO: do we really need this?
ffStrbufDestroy(&tempValue->name);
ffStrbufDestroy(&tempValue->deviceClass);
}
result /= temps.length;
return result;
}
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
FF_UNUSED(instance);
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery");
if (matchDict == NULL)
return "IOServiceMatching(\"AppleSmartBattery\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
bool boolValue;
const char* error;
BatteryResult* battery = ffListAdd(results);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
return error;
if (maxCapacity <= 0)
return "Querying MaxCapacity failed";
if ((error = ffCfDictGetInt(properties, CFSTR("CurrentCapacity"), &currentCapacity)))
return error;
if(currentCapacity <= 0)
return "Querying CurrentCapacity failed";
battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->technology);
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
{
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
ffStrbufAppendS(&battery->modelName, "Builtin");
ffStrbufAppendS(&battery->technology, "Lithium");
}
else
{
ffStrbufAppendS(&battery->manufacturer, "Unknown");
ffStrbufAppendS(&battery->modelName, "Unknown");
ffStrbufAppendS(&battery->technology, "Unknown");
}
ffStrbufInit(&battery->status);
if (!ffCfDictGetBool(properties, CFSTR("FullyCharged"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Fully charged");
else if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Charging");
else
ffStrbufAppendS(&battery->status, "");
if(instance->config.batteryTemp)
battery->temperature = detectBatteryTemp();
else
battery->temperature = FF_BATTERY_TEMP_UNSET;
CFRelease(properties);
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
return NULL;
}
-116
View File
@@ -1,116 +0,0 @@
#include "fastfetch.h"
#include "common/io.h"
#include "battery.h"
#include <dirent.h>
static void parseBattery(FFstrbuf* dir, FFlist* results)
{
uint32_t dirLength = dir->length;
FFstrbuf testBatteryBuffer;
ffStrbufInit(&testBatteryBuffer);
//type must exist and be "Battery"
ffStrbufAppendS(dir, "/type");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0)
{
ffStrbufDestroy(&testBatteryBuffer);
return;
}
//scope may not exist or must not be "Device"
ffStrbufAppendS(dir, "/scope");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
{
ffStrbufDestroy(&testBatteryBuffer);
return;
}
BatteryResult* result = ffListAdd(results);
//capacity must exist and be not empty
ffStrbufAppendS(dir, "/capacity");
bool available = ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(available)
result->capacity = ffStrbufToDouble(&testBatteryBuffer);
ffStrbufDestroy(&testBatteryBuffer);
if(!available)
{
result->capacity = 0.0/0.0;
--results->length;
return;
}
//At this point, we have a battery. Try to get as much values as possible.
ffStrbufInit(&result->manufacturer);
ffStrbufAppendS(dir, "/manufacturer");
ffReadFileBuffer(dir->chars, &result->manufacturer);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->modelName);
ffStrbufAppendS(dir, "/model_name");
ffReadFileBuffer(dir->chars, &result->modelName);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->technology);
ffStrbufAppendS(dir, "/technology");
ffReadFileBuffer(dir->chars, &result->technology);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->status);
ffStrbufAppendS(dir, "/status");
ffReadFileBuffer(dir->chars, &result->status);
ffStrbufSubstrBefore(dir, dirLength);
result->temperature = FF_BATTERY_TEMP_UNSET;
}
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
if(instance->config.batteryDir.length > 0)
{
ffStrbufAppend(&baseDir, &instance->config.batteryDir);
ffStrbufEnsureEndsWithC(&baseDir, '/');
}
else
{
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
}
uint32_t baseDirLength = baseDir.length;
DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
{
ffStrbufDestroy(&baseDir);
return "opendir(batteryDir) == NULL";
}
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
ffStrbufAppendS(&baseDir, entry->d_name);
parseBattery(&baseDir, results);
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
closedir(dirp);
if(results->length == 0) {
ffStrbufDestroy(&baseDir);
return "batteryDir doesn't contain any battery folder";
}
ffStrbufDestroy(&baseDir);
return NULL;
}
@@ -1,8 +0,0 @@
#include "fastfetch.h"
#include "battery.h"
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
FF_UNUSED(instance, results)
return "Not supported on this platform";
}
-158
View File
@@ -1,158 +0,0 @@
#include "battery.h"
#include "util/windows/unicode.h"
#include "util/mallocHelper.h"
#include <setupapi.h>
#include <batclass.h>
#include <devguid.h>
#include <winternl.h>
#include <powrprof.h>
static inline void wrapCloseHandle(HANDLE* handle)
{
if(*handle)
CloseHandle(*handle);
}
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
{
if(*hdev)
SetupDiDestroyDeviceInfoList(*hdev);
}
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
if(instance->config.allowSlowOperations)
{
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(hdev == INVALID_HANDLE_VALUE)
return "SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY) failed";
for(DWORD idev = 0;; idev++)
{
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
if(!SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did))
break;
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
if(!pdidd)
break; //Out of memory
pdidd->cbSize = sizeof(*pdidd);
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
continue;
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hBattery == INVALID_HANDLE_VALUE)
continue;
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
DWORD dwWait = 0;
DWORD dwOut;
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
continue;
BATTERY_INFORMATION bi = {0};
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
continue;
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
continue;
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
ffStrbufInitS(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
else
ffStrbufInitS(&battery->technology, "Unknown");
{
ffStrbufInit(&battery->modelName);
bqi.InformationLevel = BatteryDeviceName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->modelName, name);
}
{
ffStrbufInit(&battery->manufacturer);
bqi.InformationLevel = BatteryManufactureName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->manufacturer, name);
}
battery->temperature = 0.0/0.0;
if(instance->config.batteryTemp)
{
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
battery->temperature = temp;
}
{
BATTERY_STATUS bs;
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
else
battery->capacity = 0;
ffStrbufInit(&battery->status);
if(bs.PowerState & BATTERY_POWER_ON_LINE)
ffStrbufAppendS(&battery->status, "AC Connected, ");
if(bs.PowerState & BATTERY_DISCHARGING)
ffStrbufAppendS(&battery->status, "Discharging, ");
if(bs.PowerState & BATTERY_CHARGING)
ffStrbufAppendS(&battery->status, "Charging");
if(bs.PowerState & BATTERY_CRITICAL)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
}
else
{
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(CallNtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
battery->temperature = 0.0/0.0;
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
if(info.AcOnLine)
{
ffStrbufAppendS(&battery->status, "AC Connected");
if(info.Charging)
ffStrbufAppendS(&battery->status, ", Charging");
}
else if(info.Discharging)
ffStrbufAppendS(&battery->status, "Discharging");
}
}
return NULL;
}
-19
View File
@@ -1,19 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_bios_bios
#define FF_INCLUDED_detection_bios_bios
#include "fastfetch.h"
typedef struct FFBiosResult
{
FFstrbuf biosDate;
FFstrbuf biosRelease;
FFstrbuf biosVendor;
FFstrbuf biosVersion;
FFstrbuf error;
} FFBiosResult;
void ffDetectBios(FFBiosResult* bios);
#endif
-70
View File
@@ -1,70 +0,0 @@
#include "bios.h"
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
io_registry_entry_t registryEntry;
#ifndef __aarch64__
//https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp
//For Intel
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
ffStrbufAppendS(&bios->error, "IORegistryEntryCreateCFProperties(registryEntry) failed");
return;
}
ffCfDictGetString(properties, CFSTR("vendor"), &bios->biosVendor);
ffCfDictGetString(properties, CFSTR("version"), &bios->biosVersion);
ffCfDictGetString(properties, CFSTR("release-date"), &bios->biosDate);
if(!ffStrbufContainC(&bios->biosDate, '-'))
ffStrbufAppendS(&bios->biosRelease, "Efi-");
ffStrbufAppend(&bios->biosRelease, &bios->biosVersion);
CFRelease(properties);
IOObjectRelease(registryEntry);
return;
}
#else
//For arm64
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
{
ffCfDictGetString(properties, CFSTR("manufacturer"), &bios->biosVendor);
CFRelease(properties);
}
IOObjectRelease(registryEntry);
}
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
{
ffCfDictGetString(properties, CFSTR("system-firmware-version"), &bios->biosRelease);
ffStrbufAppend(&bios->biosVersion, &bios->biosRelease);
ffStrbufSubstrAfterFirstC(&bios->biosVersion, '-');
CFRelease(properties);
}
IOObjectRelease(registryEntry);
}
#endif
}
-26
View File
@@ -1,26 +0,0 @@
#include "bios.h"
#include <kenv.h>
static void kenvLookup(const char* name, FFstrbuf* result)
{
ffStrbufEnsureFree(result, 255);
int len = kenv(KENV_GET, name, result->chars, 256);
if(len > 0)
result->length = (uint32_t) len;
}
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
//https://wiki.ghostbsd.org/index.php/Kenv
kenvLookup("smbios.bios.reldate", &bios->biosDate);
kenvLookup("smbios.system.product", &bios->biosRelease);
kenvLookup("smbios.bios.vendor", &bios->biosVendor);
kenvLookup("smbios.bios.version", &bios->biosVersion);
}
-58
View File
@@ -1,58 +0,0 @@
#include "bios.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->biosDate);
ffStrbufInit(&bios->biosRelease);
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->biosVersion);
}
-11
View File
@@ -1,11 +0,0 @@
#include "bios.h"
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInitS(&bios->error, "Not supported on this platform");
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
}
-28
View File
@@ -1,28 +0,0 @@
#include "bios.h"
#include "util/windows/registry.h"
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &bios->error))
return;
if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->biosRelease, &bios->error))
return;
ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->biosVendor, NULL);
ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->biosDate, NULL);
uint32_t major, minor;
if(
ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) &&
ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL)
)
ffStrbufAppendF(&bios->biosVersion, "%u.%u", (unsigned)major, (unsigned)minor);
}
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_board_board
#define FF_INCLUDED_detection_board_board
#include "fastfetch.h"
typedef struct FFBoardResult
{
FFstrbuf boardName;
FFstrbuf boardVendor;
FFstrbuf boardVersion;
FFstrbuf error;
} FFBoardResult;
void ffDetectBoard(FFBoardResult* result);
#endif
-55
View File
@@ -1,55 +0,0 @@
#include "board.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInit(&board->error);
ffStrbufInit(&board->boardName);
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->boardName);
ffStrbufInit(&board->boardVendor);
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->boardVendor);
ffStrbufInit(&board->boardVersion);
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->boardVersion);
}
-10
View File
@@ -1,10 +0,0 @@
#include "board.h"
void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInitS(&board->error, "Not supported on this platform");
ffStrbufInit(&board->boardName);
ffStrbufInit(&board->boardVendor);
ffStrbufInit(&board->boardVersion);
}
-21
View File
@@ -1,21 +0,0 @@
#include "board.h"
#include "util/windows/registry.h"
void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInit(&board->error);
ffStrbufInit(&board->boardName);
ffStrbufInit(&board->boardVendor);
ffStrbufInit(&board->boardVersion);
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &board->error))
return;
if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->boardName, &board->error))
return;
ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->boardVendor, NULL);
ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->boardVersion, NULL);
}
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_chassis_chassis
#define FF_INCLUDED_detection_chassis_chassis
#include "fastfetch.h"
typedef struct FFChassisResult
{
FFstrbuf chassisType;
FFstrbuf chassisVendor;
FFstrbuf chassisVersion;
FFstrbuf error;
} FFChassisResult;
void ffDetectChassis(FFChassisResult* result);
#endif
-55
View File
@@ -1,55 +0,0 @@
#include "chassis.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
void ffDetectChassis(FFChassisResult* result)
{
ffStrbufInit(&result->error);
ffStrbufInit(&result->chassisType);
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->chassisType);
ffStrbufInit(&result->chassisVendor);
getHostValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->chassisVendor);
ffStrbufInit(&result->chassisVersion);
getHostValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->chassisVersion);
}
-10
View File
@@ -1,10 +0,0 @@
#include "chassis.h"
void ffDetectChassis(FFChassisResult* result)
{
ffStrbufInitS(&result->error, "Not supported on this platform");
ffStrbufInit(&result->chassisType);
ffStrbufInit(&result->chassisVendor);
ffStrbufInit(&result->chassisVersion);
}
-28
View File
@@ -1,28 +0,0 @@
#include "cpu.h"
#include "detection/internal.h"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu);
static void detectCPU(const FFinstance* instance, FFCPUResult* cpu)
{
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
ffDetectCPUImpl(instance, cpu);
const char* removeStrings[] = {
" CPU", " FPU", " APU", " Processor",
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core",
" with Radeon Graphics"
};
ffStrbufRemoveStringsA(&cpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
}
const FFCPUResult* ffDetectCPU(const FFinstance* instance)
{
FF_DETECTION_INTERNAL_GUARD(FFCPUResult,
detectCPU(instance, &result);
);
}
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_cpu_cpu
#define FF_INCLUDED_detection_cpu_cpu
#include "fastfetch.h"
#define FF_CPU_TEMP_UNSET (0/0.0)
typedef struct FFCPUResult
{
FFstrbuf name;
FFstrbuf vendor;
uint16_t coresPhysical;
uint16_t coresLogical;
uint16_t coresOnline;
double frequencyMin;
double frequencyMax;
double temperature;
} FFCPUResult;
const FFCPUResult* ffDetectCPU(const FFinstance* instance);
#endif
-72
View File
@@ -1,72 +0,0 @@
#include "cpu.h"
#include "common/sysctl.h"
#include "detection/temps/temps_apple.h"
static double getFrequency(const char* propName)
{
double herz = (double) ffSysctlGetInt64(propName, 0);
if(herz <= 0.0)
return herz;
herz /= 1000.0; //to KHz
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
}
static double detectCpuTemp(const FFstrbuf* cpuName)
{
FF_LIST_AUTO_DESTROY temps;
ffListInit(&temps, sizeof(FFTempValue));
if(ffStrbufStartsWithS(cpuName, "Apple M1"))
ffDetectCoreTemps(FF_TEMP_CPU_M1X, &temps);
else if(ffStrbufStartsWithS(cpuName, "Apple M2"))
ffDetectCoreTemps(FF_TEMP_CPU_M2X, &temps);
else //TODO: PPC?
ffDetectCoreTemps(FF_TEMP_CPU_X64, &temps);
if(temps.length == 0)
return FF_CPU_TEMP_UNSET;
double result = 0;
for(uint32_t i = 0; i < temps.length; ++i)
{
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
result += tempValue->value;
//TODO: do we really need this?
ffStrbufDestroy(&tempValue->name);
ffStrbufDestroy(&tempValue->deviceClass);
}
result /= temps.length;
return result;
}
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
FF_UNUSED(instance);
ffSysctlGetString("machdep.cpu.brand_string", &cpu->name);
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
if(cpu->coresPhysical == 1)
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
if(cpu->coresLogical == 1)
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
if(cpu->frequencyMax == 0.0)
cpu->frequencyMax = getFrequency("hw.cpufrequency");
if (instance->config.cpuTemp)
cpu->temperature = detectCpuTemp(&cpu->name);
else
cpu->temperature = FF_CPU_TEMP_UNSET;
}
-28
View File
@@ -1,28 +0,0 @@
#include "cpu.h"
#include "common/sysctl.h"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
FF_UNUSED(instance);
if (instance->config.cpuTemp)
{
FFstrbuf cpuTemp;
ffStrbufInit(&cpuTemp);
if(ffSysctlGetString("temperature", &cpuTemp))
cpu->temperature = FF_CPU_TEMP_UNSET;
else
cpu->temperature = ffStrbufToDouble(&cpuTemp);
}
else
cpu->temperature = FF_CPU_TEMP_UNSET;
ffSysctlGetString("hw.model", &cpu->name);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresLogical = cpu->coresPhysical;
cpu->coresOnline = cpu->coresPhysical;
cpu->frequencyMin = ffSysctlGetInt("hw.clockrate", 0) / 1000.0;
cpu->frequencyMax = cpu->frequencyMin;
}
-119
View File
@@ -1,119 +0,0 @@
#include "cpu.h"
#include "common/io.h"
#include "common/properties.h"
#include "detection/temps/temps_linux.h"
#include <sys/sysinfo.h>
#include <stdlib.h>
#include <unistd.h>
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz)
{
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
return;
char* line = NULL;
size_t len = 0;
while(getline(&line, &len, cpuinfo) != -1)
{
//Stop after the first CPU
if(cpu->name.length > 0 && (*line == '\0' || *line == '\n'))
break;
(void)(
ffParsePropLine(line, "model name :", &cpu->name) ||
ffParsePropLine(line, "vendor_id :", &cpu->vendor) ||
ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) ||
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) //For Android devices
);
}
if(line != NULL)
free(line);
fclose(cpuinfo);
}
static double getGHz(const char* file)
{
FFstrbuf content;
ffStrbufInit(&content);
if(ffAppendFileBuffer(file, &content))
{
double herz = ffStrbufToDouble(&content);
ffStrbufDestroy(&content);
//ffStrbufToDouble failed
if(herz != herz)
return 0;
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
}
return 0;
}
static double getFrequency(const char* info, const char* scaling)
{
double frequency = getGHz(info);
if(frequency > 0.0)
return frequency;
return getGHz(scaling);
}
static double detectCPUTemp(const FFinstance* instance)
{
const FFTempsResult* temps = ffDetectTemps(instance);
for(uint32_t i = 0; i < temps->values.length; i++)
{
FFTempValue* value = ffListGet(&temps->values, i);
if(
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
ffStrbufCompS(&value->name, "coretemp") == 0
) return value->value;
}
return FF_CPU_TEMP_UNSET;
}
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
if(instance->config.cpuTemp)
cpu->temperature = detectCPUTemp(instance);
else
cpu->temperature = FF_CPU_TEMP_UNSET;
FFstrbuf physicalCoresBuffer;
ffStrbufInit(&physicalCoresBuffer);
FFstrbuf cpuMHz;
ffStrbufInit(&cpuMHz);
parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz);
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
cpu->coresLogical = (uint16_t) get_nprocs_conf();
cpu->coresOnline = (uint16_t) get_nprocs();
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
if(ffFileExists(BP, S_IFDIR))
{
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
}
else
{
cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000;
}
ffStrbufDestroy(&physicalCoresBuffer);
ffStrbufDestroy(&cpuMHz);
}
-49
View File
@@ -1,49 +0,0 @@
#include "cpu.h"
#include "util/windows/registry.h"
#include "util/mallocHelper.h"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
FF_UNUSED(instance);
cpu->temperature = FF_CPU_TEMP_UNSET;
cpu->coresPhysical = cpu->coresLogical = cpu->coresOnline = 0;
cpu->frequencyMax = cpu->frequencyMin = 0;
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
{
DWORD length = 0;
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
pLogicalInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
if(pLogicalInfo && GetLogicalProcessorInformationEx(RelationProcessorCore, pLogicalInfo, &length))
{
for(
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pLogicalInfo;
(uint8_t*)ptr < ((uint8_t*)pLogicalInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
)
{
if(ptr->Relationship == RelationProcessorCore)
++cpu->coresPhysical;
}
}
}
cpu->coresOnline = (uint16_t)GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
cpu->coresLogical = (uint16_t)GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
FF_HKEY_AUTO_DESTROY hKey;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
return;
{
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
cpu->frequencyMax = mhz / 1000.0;
}
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
}
-44
View File
@@ -1,44 +0,0 @@
#include "fastfetch.h"
#include "cpuUsage.h"
#include "common/time.h"
#include <stdint.h>
// We need to use uint64_t because sizeof(long) == 4 on Windows
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
static uint64_t inUseAll1, totalAll1;
void ffPrepareCPUUsage()
{
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
}
const char* ffGetCpuUsageResult(double* result)
{
const char* error = NULL;
if(inUseAll1 == 0 && totalAll1 == 0)
{
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
if(error)
return error;
ffTimeSleep(200);
}
while(true)
{
uint64_t inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
if(error)
return error;
if(inUseAll2 != inUseAll1)
{
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
return NULL;
}
else
ffTimeSleep(200);
}
}
-8
View File
@@ -1,8 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_cpu_cpuUsage
#define FF_INCLUDED_detection_cpu_cpuUsage
const char* ffGetCpuUsageResult(double* result);
#endif

Some files were not shown because too many files have changed in this diff Show More