Compare commits

..

1059 Commits

Author SHA1 Message Date
Linus Dierheimer 4b612461b8 Merge pull request #233 from ceamac/bugs/bash-completions
Fix bash completions file
2022-09-15 18:41:25 +02:00
Viorel 38013450ae Fix bash completions file 2022-09-15 19:34:14 +03:00
Linus Dierheimer ddb0c344f5 Release 1.7.1
second try
2022-09-15 16:11:05 +02:00
Linus Dierheimer 67e433750a Release 1.7.1 2022-09-15 16:02:55 +02:00
Linus Dierheimer c4b024ec6c Update bash completion 2022-09-15 15:41:24 +02:00
Linus Dierheimer e98c18a64b Fix two compiler warnings 2022-09-15 12:10:48 +02:00
Linus Dierheimer acba1d29d9 Enable multithreading on macos 2022-09-15 11:59:06 +02:00
Linus Dierheimer dd0f6354ef MacOS custom WM support 2022-09-15 01:58:31 -07:00
Linus Dierheimer 0e2d353500 Merge pull request #232 from CarterLi/master
Improve local-ip detection on macOS and print vulkan detection failing reason
2022-09-15 09:39:14 +02:00
李通洲 f9695f4148 Vulkan: print detailed reason of why failing
instead of the general message `Failed to detect vulkan`
2022-09-15 13:32:08 +08:00
李通洲 8fdbadfbb2 LocalIp: fix --localip-show-loop on macOS
loop on macOS is `lo0`
2022-09-15 13:27:27 +08:00
Linus Dierheimer 5c43119836 Fix used disk space calculation 2022-09-14 22:35:07 +02:00
Linus Dierheimer 545210e25e Don't require FF_HAVE_OPENCL on Apple 2022-09-14 22:03:23 +02:00
Linus Dierheimer 6f60423c60 Unified gh actions for pull and push 2022-09-14 19:23:19 +02:00
Linus Dierheimer 6e6847a66b Set more values in CMake project() 2022-09-14 19:12:51 +02:00
Linus Dierheimer 47c9fb9f6c Refactore some macros 2022-09-14 19:03:50 +02:00
Linus Dierheimer 5e5c144582 Fix build on apple 2022-09-14 09:51:08 -07:00
Linus Dierheimer ac330430bf Link apple frameworks at compile time 2022-09-14 14:55:28 +02:00
Linus Dierheimer 52275b89dc Try to unify linux and apple code paths 2022-09-14 12:41:43 +02:00
Linus Dierheimer 50bb06535c Merge pull request #230 from CarterLi/master
OpenGL / OpenCL: add macOS support
2022-09-13 06:19:40 -07:00
李通洲 a8b0e77189 OpenGL / OpenCL: add macOS support
Note: FF_LIBRARY_LOAD and friends are not used because loading framework
bundles are not supported by FF_LIBRARY_LOAD and support it is not easy.
Since CGL is guaranteed to be supported by macOS system, we simply use
static linking in this case.
2022-09-13 17:03:26 +08:00
Linus Dierheimer b815464704 Merge pull request #226 from CarterLi/master
OpenGL: add macOS support with SDL2
2022-09-12 06:24:43 -07:00
李通洲 93ac3f1971 Library: simplify macros 2022-09-12 21:10:05 +08:00
Carter Li 7c43e4b8e7 ci: show everything with fastfetch 2022-09-12 21:10:05 +08:00
Linus Dierheimer d8e7588fc3 Merge pull request #229 from Evo112358/master
Issue 223 pull request
2022-09-12 00:42:16 -07:00
Evo112358 9ea5de5efc updated --help terminal-format 2022-09-12 15:57:05 +10:00
Evo112358 728759d38e pull request to implement enhancement referenced in issue 223. 2022-09-12 15:51:53 +10:00
Linus Dierheimer b0426828ab Slackware logos
#228
2022-09-11 21:10:32 +02:00
Linus Dierheimer 6de8153207 Make media detection more robust 2022-09-11 13:09:33 +02:00
Linus Dierheimer 2c4b80a093 Fix ENABLE_ZLIB requirements 2022-09-11 12:03:01 +02:00
Linus Dierheimer c51903da35 GH Actions: share version as output 2022-09-11 11:56:00 +02:00
Linus Dierheimer 8b7092e4d4 gpu_apple.c: Use Ascii encoding 2022-09-11 02:44:19 -07:00
Linus Dierheimer c54b7fbd57 Restore permissions after artifact upload 2022-09-11 11:10:02 +02:00
Linus Dierheimer 820854a2fa Fix release action 2022-09-11 10:56:54 +02:00
Linus Dierheimer ad4a71a2d5 Github actions: package for all platforms 2022-09-11 10:47:47 +02:00
Linus Dierheimer 22075e2d28 CMake: keep sysconfdir in cache 2022-09-09 22:43:53 +02:00
Linus Dierheimer a926c9cf7e Use vulkan as gpu fallback on all platforms 2022-09-09 20:43:24 +02:00
Linus Dierheimer 60c735d1a4 Enable Vulkan on MacOS 2022-09-09 20:37:56 +02:00
Linus Dierheimer 9466ee3e51 Even better GPU names 2022-09-09 17:53:19 +02:00
Linus Dierheimer 126c1a10bb Correctly handle GPU names with multiple ']' 2022-09-09 17:48:55 +02:00
Linus Dierheimer 425e135bd8 Reintroduce gpu name modification 2022-09-09 17:47:16 +02:00
Linus Dierheimer 0a675fec8c Give libpci a bigger buffer to work with
#224
2022-09-09 17:40:08 +02:00
Linus Dierheimer 2c5b079b97 Apple M1 GPU support 2022-09-09 05:40:27 -07:00
Linus Dierheimer 0be1a41b5c Update gpu_apple.c 2022-09-08 17:33:29 +02:00
Linus Dierheimer 883e0450b0 Correct intendation 2022-09-08 15:27:53 +02:00
Linus Dierheimer 2fc8a7e70b Better brew package detection 2022-09-08 06:26:26 -07:00
Linus Dierheimer be7f8f4117 Swap module
#225
2022-09-08 14:51:31 +02:00
Linus Dierheimer dd60e8aa75 fix build on macos 2022-09-08 01:50:18 -07:00
Linus Dierheimer 851899397e Improve brew package detection 2022-09-08 10:45:56 +02:00
Linus Dierheimer 60a30d888f GitHub actions: don't try to build deb on macos second try 2022-09-07 21:00:13 +02:00
Linus Dierheimer 999c8208b7 GitHub actions: don't try to build deb on macos 2022-09-07 20:58:14 +02:00
Linus Dierheimer 9143b6dbec GitHub actions: build on macos too 2022-09-07 20:56:19 +02:00
Linus Dierheimer 16a706d3c5 Seperate color config of title and keys 2022-09-07 19:50:10 +02:00
Linus Dierheimer 58f436d8a2 Apple GPU: Set length of name buffer 2022-09-07 06:40:47 -07:00
Linus Dierheimer 47d1f2e673 Try to fix gpu_apple
#222
2022-09-07 06:37:35 -07:00
Linus Dierheimer 8be4921bd0 Release 1.7.0 2022-09-06 18:59:03 +02:00
Linus Dierheimer b22bcba220 Don't use LC_CTYPE for locale detection 2022-09-06 09:17:26 -07:00
Linus Dierheimer 5ee7ea46e7 Better variable naming 2022-09-06 18:03:31 +02:00
Linus Dierheimer d93c934269 MacOS Resolution support 2022-09-06 08:04:45 -07:00
Linus Dierheimer 5c1ac33df2 MacOS WM & DE support 2022-09-06 06:52:50 -07:00
Linus Dierheimer 0b3bf3c273 Only build display server code on linux 2022-09-06 15:42:37 +02:00
Linus Dierheimer 7fd98829b0 Fix unused variable 2022-09-06 14:23:07 +02:00
Linus Dierheimer 282271a65a MacOS disk support 2022-09-06 05:19:21 -07:00
Linus Dierheimer 9ef4b82cb9 Refactor disk module 2022-09-06 13:24:57 +02:00
Linus Dierheimer 10973dd9d1 Better MacOS GPU support 2022-09-06 02:28:32 -07:00
Linus Dierheimer dfdffec1c9 MacOS GPU support 2022-09-05 13:41:05 -07:00
Linus Dierheimer 2283700a99 Refactor CMakeLists.txt 2022-09-05 19:56:00 +02:00
Linus Dierheimer 7b647e09da Only enable library features on linux by default 2022-09-05 18:30:30 +02:00
Linus Dierheimer 54cb74c999 Separate gpu detection and printing logic 2022-09-05 17:42:42 +02:00
Linus Dierheimer 0f70cb408f Updated presets 2022-09-05 16:11:35 +02:00
Linus Dierheimer c80b1761dd brew package support 2022-09-05 05:15:19 -07:00
Linus Dierheimer a1fde6f922 MacOS memory support 2022-09-05 02:46:53 -07:00
Linus Dierheimer 6a44515cf2 Separate memory detection and printing logic 2022-09-05 10:57:09 +02:00
Linus Dierheimer cfcc4c8375 MacOS cpu support 2022-09-04 14:12:04 -07:00
Linus Dierheimer ea60fd0a0d Separate cpu detection and printing logic 2022-09-04 22:20:12 +02:00
Linus Dierheimer a4e0275263 Update README.md 2022-09-04 18:07:15 +02:00
Linus Dierheimer 71779fa4b1 Basic MacOS support 2022-09-04 09:02:11 -07:00
Linus Dierheimer 475099696f MacOS logo 2022-09-04 16:32:45 +02:00
Linus Dierheimer 14670b6144 Always cast to right tv_usec type 2022-09-04 14:41:00 +02:00
Linus Dierheimer 327b1b142e guard get_nproc with FF_HAVE_SYSCONF_H 2022-09-04 14:37:57 +02:00
Linus Dierheimer 9d106c6672 Enable build on MacOS
Note that this commit just makes fastfetch compile, not work properly
2022-09-04 14:30:52 +02:00
Linus Dierheimer df0e13b198 Fix possible segfault 2022-09-04 13:56:14 +02:00
Linus Dierheimer 6d0675820e Fix build on Android 2022-09-04 13:36:56 +02:00
Linus Dierheimer 08b0bac2b9 Refactor os detection code 2022-09-04 13:33:18 +02:00
Linus Dierheimer d387800bda Separate host detection and printing logic 2022-09-04 12:43:30 +02:00
Linus Dierheimer 542ad5eab6 Small fixes to gpu code 2022-09-03 10:53:30 +02:00
Linus Dierheimer 99f42d0953 Fix build with old libpci versions 2022-09-01 17:22:35 +02:00
Linus Dierheimer 3b316bdd3f Refactor pci code 2022-09-01 17:14:50 +02:00
Linus Dierheimer f011f8851e recache between commits too 2022-09-01 17:14:10 +02:00
Linus Dierheimer 8f23a52f53 Fix typos 2022-08-30 19:46:36 +02:00
Linus Dierheimer 8f53d33f29 Fix --file option 2022-08-29 11:01:29 +02:00
Linus Dierheimer e6fa269f52 Update README.md 2022-08-29 09:24:03 +02:00
Linus Dierheimer ca4a327de4 Update README.md 2022-08-28 18:42:53 +02:00
Linus Dierheimer f4e777f3d2 Update README.md 2022-08-28 18:34:54 +02:00
Linus Dierheimer 136f73ea0b Updated screenshots 2022-08-28 17:39:01 +02:00
Linus Dierheimer 28270541e6 use pci_read_byte to support older libpci versions 2022-08-28 16:01:34 +02:00
Linus Dierheimer 8197eddea8 Much better AMD gpu names 2022-08-28 15:51:28 +02:00
Linus Dierheimer 23bccc4802 MSYS2 logo
#219
2022-08-27 16:15:31 +02:00
Linus Dierheimer 873c7d93b6 Fix ffStrSet 2022-08-27 12:22:03 +02:00
Linus Dierheimer f4ee8667b1 Binary prefix option 2022-08-26 16:02:04 +02:00
Linus Dierheimer 50d3d4cdf4 Merge pull request #220 from sirlucjan/patch-1
Add CachyOS small logo
2022-08-25 12:41:51 +02:00
Piotr Gorski df048035b5 Add CachyOS small logo
Signed-off-by: Piotr Gorski <lucjan.lucjanov@gmail.com>
2022-08-24 20:44:36 +02:00
Linus Dierheimer 952989c1e8 Show huge ram values in GiB
#218
2022-08-23 13:53:12 +02:00
Linus Dierheimer aa1237b0fd Simplified config file loading logic 2022-08-22 12:45:20 +02:00
Linus Dierheimer b87983c86b Fix parsing quoted values in config files 2022-08-22 12:14:08 +02:00
Linus Dierheimer 779dbab647 Release 1.6.4 2022-08-22 00:13:13 +02:00
Linus Dierheimer 47373998d5 replace gethostbyname with getaddrinfo
#217
2022-08-21 23:35:22 +02:00
Linus Dierheimer 11809e30b5 Parse config files faster 2022-08-21 21:08:11 +02:00
Linus Dierheimer 35253e085c Unified storage of --set and --set-keyless values 2022-08-20 18:17:00 +02:00
Linus Dierheimer 112e83b7c3 Provide apk count to package format string 2022-08-18 22:02:21 +02:00
Linus Dierheimer c74b34aa39 Merge pull request #216 from mxkrsv/apk-support
Add APK (Alpine Package Keeper) support
2022-08-18 21:56:20 +02:00
Maxim Karasev b2e0034c34 Add APK (Alpine Package Keeper) support 2022-08-18 22:28:40 +03:00
Linus Dierheimer e3cdf9d9fd Reset color after custom module 2022-08-18 11:45:44 +02:00
Linus Dierheimer 6cdb694e33 Do simple \ replacement in user strings 2022-08-18 11:36:30 +02:00
Linus Dierheimer 83016289e9 --set-keyless option 2022-08-18 10:44:21 +02:00
Linus Dierheimer f9562d7132 Merge pull request #214 from jonathanspw/master
add AlmaLinux logo
2022-08-17 09:19:38 +02:00
jonathanspw 2f66bc2c95 add AlmaLinux logo 2022-08-16 20:10:47 -05:00
Linus Dierheimer d7c848225c Update CHANGELOG.md 2022-08-12 21:52:29 +02:00
Linus Dierheimer 8404ae8e70 Merge pull request #212 from ceamac/bugs/install-presets
Fix installation of presets/ directory
2022-08-12 21:50:49 +02:00
Viorel d75f72c8fe Fix installation of presets/ directory 2022-08-12 22:35:31 +03:00
Linus Dierheimer 9fa00081e3 Release 1.6.2 2022-08-12 16:01:52 +02:00
Linus Dierheimer fca37b59c8 Print xbps package count once again
#209
2022-08-12 09:40:02 +02:00
Linus Dierheimer 2fe7476c67 Better xbps package count
#209
2022-08-07 19:42:16 +02:00
Linus Dierheimer 03cbd64d8a Merge pull request #208 from hervyqa/langitketujuh
Add LangitKetujuh Linux logo
2022-08-03 13:03:06 +02:00
Hervy Qurrotul Ainur Rozi f65aeed96f Add LangitKetujuh Linux logo 2022-08-03 16:46:14 +07:00
Linus Dierheimer b63f419cde Merge pull request #207 from draumaz/master
Add KISS Linux logo
2022-08-02 15:14:41 +02:00
draumaz 99aa2f7b45 swap order 2022-08-02 12:29:44 +00:00
draumaz b251c32c12 fix colors, update README 2022-08-02 12:24:15 +00:00
draumaz 034e23d7e3 Merge branch 'LinusDierheimer:master' into master 2022-08-02 05:13:30 -07:00
Linus Dierheimer bba912d42e Add missing include 2022-08-02 10:24:54 +02:00
draumaz 597652c35a one more backslash 2022-08-02 05:56:20 +00:00
draumaz 7f67846ad9 add KISS Linux logo 2022-08-02 05:51:15 +00:00
Linus Dierheimer bc2e292e22 Update issue templates 2022-07-31 17:44:07 +02:00
Linus Dierheimer 75dc228120 Update issue templates 2022-07-31 17:39:54 +02:00
Linus Dierheimer bc783f6efd Update issue templates 2022-07-31 17:33:03 +02:00
Linus Dierheimer 85e1d2b40c Add logo request template 2022-07-31 17:31:30 +02:00
Linus Dierheimer 3338189354 Rosa Linux logo 2022-07-31 17:22:03 +02:00
Linus Dierheimer d4c836fd25 Handle empty xdg env vars better 2022-07-30 23:30:46 +02:00
Linus Dierheimer 6787f1eba8 Merge branches 'master' and 'master' of github.com:LinusDierheimer/fastfetch 2022-07-27 21:56:42 +02:00
Linus Dierheimer eedc277bcf Respect target dir config during installation 2022-07-27 21:56:28 +02:00
Linus Dierheimer d4b32eaaec Merge pull request #205 from licy183/fix-android-header
Fix build error on Android
2022-07-27 19:31:29 +02:00
Linus Dierheimer 910f63f0ad Update changelog 2022-07-27 19:31:14 +02:00
Linus Dierheimer 9a0aa2ac72 Fix compilation issues
1) when building for android
2) when building without wayland
2022-07-27 19:28:55 +02:00
Chongyun Lee dce81055fe Release 1.6.1 2022-07-28 01:28:17 +08:00
Chongyun Lee 66a4fc1600 Fix build error on Android
host.c has an #elif, but actually #else is needed.
2022-07-27 22:50:11 +08:00
Linus Dierheimer 159a114bb7 Release 1.6.0
tag correctly
2022-07-26 22:38:40 +02:00
Linus Dierheimer ac08b46e71 Release 1.6.0
this time with correct packaging the second
2022-07-26 22:27:13 +02:00
Linus Dierheimer ceb92dafd7 Release 1.6.0
this time with correct packaging
2022-07-26 22:13:09 +02:00
Linus Dierheimer 31eeb6dd08 Release 1.6.0 2022-07-26 20:35:15 +02:00
Linus Dierheimer c021689a2b Better nix package sorting
#195
2022-07-26 19:15:00 +02:00
Linus Dierheimer 2ac2762c9f Print nix-default packages
#195
2022-07-26 19:03:15 +02:00
Linus Dierheimer 27dd097671 Improved Nix package detection
#195
2022-07-26 18:36:10 +02:00
Linus Dierheimer c7bf471e29 Refactor: move vulkan detection to own header 2022-07-26 18:18:14 +02:00
Linus Dierheimer 298bc10e5f Refactor: move media detection to own header 2022-07-26 18:15:45 +02:00
Linus Dierheimer 676485ef74 Refactor: move temps detection to own header 2022-07-26 18:13:12 +02:00
Linus Dierheimer fb6da20b0c Refactor: move date/time detection to own header 2022-07-26 18:09:25 +02:00
Linus Dierheimer 0c81d3e894 Refactor: move terminal/shell detection to own header 2022-07-26 18:06:30 +02:00
Linus Dierheimer 5c1aa20042 Refactor: move wm/de detection to own header 2022-07-26 17:56:42 +02:00
Linus Dierheimer 46a27c4e39 Refactor: move gtk detection to own header 2022-07-26 17:47:08 +02:00
Linus Dierheimer 128302596e Refactor: move qt detection to own header 2022-07-26 17:42:28 +02:00
Linus Dierheimer 7a15dee2be Refactor: move os detection to own header 2022-07-26 17:33:51 +02:00
Linus Dierheimer 000bd37f1d Refactor: move title detection to own header 2022-07-26 17:29:09 +02:00
Linus Dierheimer 707e0f930d Refactor: don't include FFvaluestore global 2022-07-25 19:54:33 +02:00
Linus Dierheimer 7676a313c5 Refactor: move threading functions to init 2022-07-25 15:01:11 +02:00
Linus Dierheimer 6e0d76a2fb Refactor: move networking functions to own header 2022-07-25 14:48:59 +02:00
Linus Dierheimer 4c7b7e4a4d Refactor: move processing functions to own header 2022-07-25 14:45:41 +02:00
Linus Dierheimer 4d34091573 Refactor: move format functions to own header 2022-07-25 14:26:08 +02:00
Linus Dierheimer c971e28aca Refactor: move setting functions to own header 2022-07-25 14:20:07 +02:00
Linus Dierheimer c41a29a5c1 Refactor: move parsing functions to own header 2022-07-25 13:59:19 +02:00
Linus Dierheimer 5c73125693 Refactor: move font functions to own header 2022-07-25 13:44:55 +02:00
Linus Dierheimer cea48474a1 Refactor: move caching functions to own header 2022-07-25 13:36:58 +02:00
Linus Dierheimer 536f914f3e Refactor: move printing functions to own header 2022-07-25 13:15:01 +02:00
Linus Dierheimer 778856dd57 Refactor: move property functions to own header 2022-07-25 12:24:23 +02:00
Linus Dierheimer 4a43144991 Refactor: move io functions to own header 2022-07-25 11:48:48 +02:00
Linus Dierheimer ac96cfc748 Refactor: move FFInitState to settings.c 2022-07-25 11:24:50 +02:00
Linus Dierheimer f18ffe3239 Refactor: move library functions and macros to own header 2022-07-25 11:20:38 +02:00
Linus Dierheimer 986bbeebb3 Don't segfault if invalid structure is given
#204
2022-07-25 11:00:41 +02:00
Linus Dierheimer b9d360af97 --title-fqdn option
#203
2022-07-22 19:36:00 +02:00
Linus Dierheimer ec1981c545 Use [QT] instead of [Plasma]
#198 #199
2022-07-22 17:18:36 +02:00
Linus Dierheimer f7e7d8e9f2 Update README.md 2022-07-22 13:42:26 +02:00
Linus Dierheimer ad9fc5845a GTK: Fix detection on XFCE DE
#198 #199
2022-07-22 12:23:35 +02:00
Linus Dierheimer a6b169f3e2 Disk: Print one decimal point if < 100GiB
#202
2022-07-22 11:47:20 +02:00
Linus Dierheimer 8aff9939bc GTK: prefer dconf over config files on certain DEs
#198 #199
2022-07-22 11:24:29 +02:00
Linus Dierheimer 0b8f51188b gh actions: configure correct path for packaging
the follow up
2022-07-21 22:58:38 +02:00
Linus Dierheimer 3c99a82619 gh actions: configure correct path for packaging 2022-07-21 22:55:47 +02:00
Linus Dierheimer d5f3ff1cfe Update README.md 2022-07-21 20:20:40 +02:00
Linus Dierheimer 011c033091 Update README.md 2022-07-21 20:18:34 +02:00
Linus Dierheimer 63bf22fb00 Load system config
#196
2022-07-21 14:37:13 +02:00
Linus Dierheimer f74973db65 Special NixOS OS output
#194
2022-07-21 11:33:19 +02:00
Linus Dierheimer 85656fd515 Fix Mutter detection
#200
2022-07-20 21:32:17 +02:00
Linus Dierheimer 23bf7a407b Fix alacritty term font size
#197
2022-07-20 20:56:02 +02:00
Linus Dierheimer e570cacbc9 Fix typos
#201
2022-07-20 20:44:16 +02:00
Linus Dierheimer a96f79795b Merge pull request #193 from Izorkin/update-nixos-logo
Update old nixos logo
2022-07-19 12:09:25 +02:00
Izorkin 2d51d935c8 update old nixos logo 2022-07-19 12:57:15 +03:00
Linus Dierheimer 9d395f7235 don't print GPU in WSL 2022-07-17 16:11:08 +02:00
Linus Dierheimer 5f16394916 Add alacritty to readme 2022-07-12 16:49:39 +02:00
Linus Dierheimer 6581c9d378 Merge pull request #191 from x-zvf/alacritty-term-support
[enhancement] Add best effort terminal font detection for alacritty.
2022-07-12 16:46:22 +02:00
Péter Bohner (xzvf) 67ac7eef59 buxfix: missing fontSize/fontName would overwrite the other 2022-07-12 16:43:21 +02:00
Péter Bohner (xzvf) b95e83e9e5 Use ffStrbufAppend instead of ffStrbugInitCopy 2022-07-12 16:41:20 +02:00
Péter Bohner (xzvf) e9d9b942fa Cleanup diff 2022-07-12 16:34:35 +02:00
Péter Bohner (xzvf) c95ad74ea2 Refactor to use ffFontInitCopy and detect font size
printAlacritty now usese ffFontInitCopy instead of ffFontInitPango
and also detects font size.
2022-07-12 16:31:19 +02:00
Péter Bohner (xzvf) 85b0be5213 Add best effort terminal font detection for alacritty.
Alacritty's config files are technically YML files, so
simply looking for a prop value "family:" may break some of the time,
but is in fact better than what neofetch does and much easier
to implement then writing a YML parser :)
2022-07-12 14:38:06 +02:00
Linus Dierheimer da671d6cfe Start cleaning up of config struct 2022-07-10 18:28:17 +02:00
Linus Dierheimer 18af9ab902 Wayland: don't destroy proxies our self 2022-07-08 11:48:43 +02:00
Linus Dierheimer 558fbc20e2 Don't detect guake-wrapped as terminal 2022-07-08 11:24:11 +02:00
Linus Dierheimer d9bbbd4fa8 Merge pull request #189 from x-zvf/alacritty-term-support
Fix memory leak in ffParsePropFileValues
2022-07-08 10:46:11 +02:00
Péter Bohner (xzvf) 292a809703 ffParsePropValues: Hoisted fopen call to simplify error handling 2022-07-08 09:09:59 +02:00
Péter Bohner (xzvf) fa13826043 Revert "Coalesce cleanup in ffParsePropFileValues"
This reverts commit 7bc85b2397.
2022-07-08 09:05:00 +02:00
Péter Bohner (xzvf) 7bc85b2397 Coalesce cleanup in ffParsePropFileValues 2022-07-07 15:19:56 +02:00
Péter Bohner (xzvf) 1863d8377a Fix memory leak in ffParseProfFileValues, if more than 4 queries are passed (unsetValues is on the heap) and the file
is not found.
2022-07-07 14:35:59 +02:00
xzvf f9e17f44b1 Merge branch 'LinusDierheimer:master' into master 2022-07-04 20:10:01 +02:00
Linus Dierheimer 02cc214dfc Release 1.5.6
Bugfix: Don't segfault when connecting to some wayland compositors
See https://github.com/LinusDierheimer/fastfetch/issues/188
2022-07-03 16:16:39 +02:00
Linus Dierheimer 609fa14f4f Wayland: use a single, common stub listener 2022-07-03 16:10:17 +02:00
Linus Dierheimer 7d6f92a446 Wayland: only use required stub listeners 2022-06-30 12:22:46 +02:00
Linus Dierheimer bc76ebfb3f Wayland: add stub listeners 2022-06-30 12:16:38 +02:00
Linus Dierheimer c2da7b19f9 Song: Don't show album by default 2022-06-29 12:47:57 +02:00
Linus Dierheimer 41b024d3b1 Refactor wayland code the third 2022-06-29 11:08:42 +02:00
Linus Dierheimer 9b62d17d8d Refactor wayland code the second 2022-06-28 21:41:13 +02:00
Linus Dierheimer 1861d55f7d Refactor wayland code 2022-06-28 11:57:08 +02:00
Linus Dierheimer 3b2a6e4a6e Don't load sqlite3 id db path doesn't exist 2022-06-27 15:38:34 +02:00
Linus Dierheimer 8ab7a8ba37 Release 1.5.5
Feature: Detect wayland WM much faster
Bugfix: Wayland backend for resolution working once again
Bugfix: Plasma values are no longer victims to race conditions
2022-06-26 13:41:55 +02:00
Linus Dierheimer 22a3ab4a81 Detect wayland WM _much_ faster 2022-06-26 13:35:16 +02:00
Linus Dierheimer 44d6780545 Merge pull request #185 from artixnous/master
Fix misaligned Artix logo
2022-06-25 17:41:16 +02:00
nous 5820c9bbff Update builtin.c 2022-06-25 13:26:07 +03:00
Linus Dierheimer 3ba486a5b8 Wayland: switch to wl_proxy_marshal_constructor_versioned 2022-06-23 15:59:59 +02:00
Linus Dierheimer 2d2ba4c5b3 Wayland: switch to wl_proxy_marshal_flags 2022-06-23 15:51:29 +02:00
Linus Dierheimer 94ad782caa No unneeded casts 2022-06-23 10:44:53 +02:00
Linus Dierheimer b079e86c5e update bug_report.yml 2022-06-23 10:36:53 +02:00
Linus Dierheimer 91ba03d988 Add warning about public IP to bug_report.yml 2022-06-23 10:35:46 +02:00
Linus Dierheimer c440fdfca8 Uses instance->state.configDirs consistenlty (in particular thread save) troughout the project 2022-06-22 20:14:10 +02:00
Linus Dierheimer af0c72aa61 Methods for caching generic data 2022-06-20 16:35:15 +02:00
Linus Dierheimer 8fa09ca093 Refactored read methods 2022-06-20 16:27:33 +02:00
Linus Dierheimer 6e731c80d0 Refactored write methods 2022-06-19 18:22:00 +02:00
Linus Dierheimer 45eae78980 Better ordering in initCacheDir 2022-06-19 18:21:41 +02:00
Linus Dierheimer fb35a6e889 Release 1.5.4
Feature: Better WSL / WSLg support
Feature: --<module>-error arguments
Bugfix: Show GiB instad of GB
Feature: Export much more information to host format string
Feature: Expose CPU temp to cpu format string
Feature: Expose GPU temp to gpi format string
Bugfix: Print last line of logo, if it is higher than the infos
Logo: Alpine Linux
Refactor: Cleaned up header includes
Refactor: Build libfastfetch as OBJECT lib, as the linked binary is never needed
Feature: Detect termux as terminal
2022-06-18 23:39:48 +02:00
Linus Dierheimer 26d17250b6 Detect WSLg 2022-06-18 14:55:56 +02:00
Linus Dierheimer 9176797327 Detect Windows Terminal better 2022-06-18 14:51:10 +02:00
Linus Dierheimer 9d3f762c20 Better fallback for wayland detection 2022-06-18 15:27:46 +02:00
Linus Dierheimer fe71291769 Clean up includes 2022-06-18 14:25:31 +02:00
Linus Dierheimer f35dc9f46a Detect termux 2022-06-18 00:45:28 +02:00
Linus Dierheimer a6209187ae Fix build on Android part 4 2022-06-18 00:41:43 +02:00
Linus Dierheimer af2f97e0c9 Fix build on Android part 3 2022-06-18 00:22:07 +02:00
Linus Dierheimer 0691112e5e Fix build on Android part 2 2022-06-18 00:20:22 +02:00
Linus Dierheimer e61b31acab Fix build on Android 2022-06-18 00:15:23 +02:00
Linus Dierheimer 5d853f3b17 GPU temp detection 2022-06-17 23:38:33 +02:00
Linus Dierheimer 20e2f1e19d Detect CPU temp only if a custom format string is given 2022-06-17 20:41:11 +02:00
Linus Dierheimer ad28b3aac5 rename date-time to datetime 2022-06-17 20:40:51 +02:00
Linus Dierheimer eb0bbd0796 Detect WSL as host name 2022-06-17 20:01:02 +02:00
Linus Dierheimer da77a7936f Detect WSL as host 2022-06-17 19:59:01 +02:00
Linus Dierheimer eac875b8b1 Update bash completion to include --<module>-error options 2022-06-17 18:28:37 +02:00
Linus Dierheimer 97d2096df8 Delete performance test
I never really used it, and it didn't even build any more
2022-06-17 18:19:53 +02:00
Linus Dierheimer 6e3e717224 --<module>-error options 2022-06-17 18:15:36 +02:00
Linus Dierheimer aae182c889 Merge pull request #180 from draumaz/master
Add Alpine Linux logos
2022-06-17 10:44:54 +02:00
draumaz 5c7b9d223a Merge pull request #1 from draumaz/workbench
Merge Alpine Linux logos
2022-06-17 04:12:50 +00:00
draumaz c80f8cf422 further fixes 2022-06-16 21:11:14 -07:00
draumaz b150e8d106 whoops 2022-06-16 21:10:23 -07:00
draumaz bb897f03f0 add small logo 2022-06-16 21:08:39 -07:00
draumaz 517d80eadc update getAll function 2022-06-16 21:03:39 -07:00
draumaz 36964d6b1d Initial Alpine addition 2022-06-16 21:02:20 -07:00
Linus Dierheimer 5e96ba8384 Fix cpu temp detection the second 2022-06-16 14:55:02 +02:00
Linus Dierheimer 481affa50a Fix cpu temp detection 2022-06-16 14:39:01 +02:00
Linus Dierheimer a33e296656 Merge pull request #178 from Samisafool/patch-1
fix spelling of temperature
2022-06-16 14:17:07 +02:00
Samisafool 85a36ae7ef fix spelling of temperature 2022-06-16 17:10:59 +05:30
Linus Dierheimer 1eff343733 Finish exposing temperatur to cpu format 2022-06-16 13:36:00 +02:00
Linus Dierheimer acdbf6933c Merge pull request #177 from x-zvf/feature-cpu-temp
Add CPU package temperature to CPU module.
2022-06-16 13:21:34 +02:00
xzvf ea53833466 Remove unnecessary checks for content->length 2022-06-16 13:18:38 +02:00
xzvf c491c11988 update DEVELOPMENT.md 2022-06-16 13:15:48 +02:00
xzvf dcaeab7e96 Rewrite to use ffDetectTemps. 2022-06-16 13:14:03 +02:00
xzvf bccd1cf960 Merge pull request #1 from LinusDierheimer/master
build temps file
2022-06-16 13:14:03 +02:00
xzvf 5b030de20a Quality of life improvement: make run.sh not run ff, if the build fails 2022-06-16 13:14:03 +02:00
xzvf fa9b38eb2d Merge pull request #1 from LinusDierheimer/master
build temps file
2022-06-16 12:54:28 +02:00
Linus Dierheimer 716522e29a build temps file 2022-06-15 23:15:49 +02:00
Linus Dierheimer 921e4a6c8d Merge pull request #176 from x-zvf/fix-run-sh-script
Quality of life improvement: make run.sh not run ff, if the build fails
2022-06-15 16:43:59 +02:00
xzvf 7d43118abb Quality of life improvement: make run.sh not run ff, if the build fails 2022-06-15 16:28:07 +02:00
xzvf d8bb36f119 Add CPU package temperature to CPU module.
This is done by looking for a specified thermal zone in
/sys/class/thermal/thermal_zone*/ .
Unfortunately there is no better way to find the
temperature, then to check all registered zones.
This still needs to be extended to support other hardware,
right now only x86 CPUs and Raspberry pi are tested.
Maybe the FF_CPU_THERMAL_ZONES array could be user configurable,
but I could not figure out how to add an array as a config parameter.
2022-06-15 16:21:50 +02:00
Linus Dierheimer ae8b5bde65 Fix printing of remaining logo 2022-06-15 11:07:22 +02:00
Linus Dierheimer 3d8a071781 Update verbose 2022-06-14 20:07:42 +02:00
Linus Dierheimer 4cf912e535 Disk: Change GB to GiB 2022-06-14 17:17:22 +02:00
Linus Dierheimer e1b5445783 Export much more values to host format string 2022-06-14 17:10:46 +02:00
Linus Dierheimer a04daf1fff Clean up git ignore 2022-06-13 21:28:49 +02:00
Linus Dierheimer df0a4c0d46 Remove unneeded property set from CMakeLists.txt 2022-06-11 14:17:10 +02:00
Linus Dierheimer d70e160d72 Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2022-06-10 23:02:11 +02:00
Linus Dierheimer 8c52cd0d91 Change libfastfetch target to be OBJECT library 2022-06-10 23:01:56 +02:00
Linus Dierheimer 4622d7a300 Change libfatsfetch target to be OBJECT library 2022-06-10 22:58:35 +02:00
Linus Dierheimer 09f7180dd5 Merge pull request #169 from ADawesomeguy/patch-1
fix: correct "hout" to "hour"
2022-06-10 22:37:07 +02:00
Abheek Dhawan 6ae8b46f68 fix: correct "hout" to "hour" 2022-06-10 15:12:39 -05:00
Linus Dierheimer 2d0ffb55b7 Release 1.5.3
Enable LTO by default
Fix compile bug when LTO enabled
2022-06-08 17:18:02 +02:00
Linus Dierheimer 22a8cfdcfe Remove obsolete strbuf function 2022-06-08 17:14:11 +02:00
Linus Dierheimer 63041aa24b Enable link time optimization 2022-06-08 16:25:14 +02:00
Linus Dierheimer 242df5f2f0 Explicitly set c standard to 11 2022-06-08 15:52:55 +02:00
Linus Dierheimer ec1bbd118f Update README.md 2022-06-08 12:11:00 +02:00
Linus Dierheimer fe624123dc Merge pull request #168 from Yureien/master
Fix build if ImageMagick is not installed
2022-06-08 12:08:10 +02:00
Linus Dierheimer 8577be3d6d Update packaging section in README 2022-06-08 12:07:06 +02:00
Soham Sen d185dc74b8 Bumped version to 1.5.2 2022-06-08 15:32:52 +05:30
Soham Sen 54c09cab18 Fix build if ImageMagick is not installed 2022-06-08 15:22:34 +05:30
Linus Dierheimer dbe24c7508 Fix --print-logos 2022-06-08 11:28:26 +02:00
Linus Dierheimer d23d4ef5a0 Relase 1.5.0
Module: Vulkan
Module: OpenGL
Module: OpenCL
Feature: Detect Bedrock linux
Feature: Detect packages on Bedrock linux
Feature: --pipe option
Logo: Bedrock linux
Bugfix: Locale detection on Ubuntu and deriviates
Bugfix: bolt keys and title, if main color is not set
2022-06-08 11:17:08 +02:00
Linus Dierheimer daac1b783c Refactored logo choosing logic 2022-06-08 10:59:33 +02:00
Linus Dierheimer 2e98dd7710 Move ffPrintLogoAndKey to printing.c 2022-06-06 14:30:06 +02:00
Linus Dierheimer 9d6d2ca5a4 Add osmesa to help texts 2022-06-06 14:24:14 +02:00
Linus Dierheimer e4a1a836fe Fix keys not being bolt if main color is not set 2022-06-06 14:20:05 +02:00
Linus Dierheimer 1e3cabff2d --pipe option 2022-06-06 14:02:21 +02:00
Linus Dierheimer 008cf3b83d OpenCL module 2022-06-05 00:18:40 +02:00
Linus Dierheimer 3daede53eb Don't cache OS 2022-06-04 22:43:57 +02:00
Linus Dierheimer 36d9b5a9bd Finish OpenGL module 2022-06-04 19:30:26 +02:00
Linus Dierheimer 1826e23c29 OpenGL module 2022-06-04 15:21:34 +02:00
Linus Dierheimer 43b3998b9d Fix bedrock linux detection 2022-06-03 01:48:50 +02:00
Linus Dierheimer c55cc9c732 ffParsePropFileValues: only allocate storage on the heap if numQuerys > 4 2022-06-03 00:24:53 +02:00
Linus Dierheimer 0244e5ebd7 removed unused code 2022-06-02 23:24:50 +02:00
Linus Dierheimer ea6805de82 Escape bedrock option 2022-06-02 23:06:49 +02:00
Linus Dierheimer 9aba57cdea Bedrock package support 2022-06-02 22:58:19 +02:00
Linus Dierheimer 0dffd8debf Vulkan module 2022-06-01 00:04:58 +02:00
Linus Dierheimer 032ba375b6 Enable chafa only if ImageMagick is found 2022-05-29 16:23:56 +02:00
Linus Dierheimer 743bc07bad Correctly detect locale on ubuntu systems 2022-05-29 16:17:36 +02:00
Linus Dierheimer 044e5496fd Fix bedrock logo 2022-05-25 14:28:08 +02:00
Linus Dierheimer 102b2d33c7 Bedrock linux detection 2022-05-25 14:06:59 +02:00
Linus Dierheimer afc144fa01 Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2022-05-25 14:00:36 +02:00
Linus Dierheimer ededa4d6dd Bedrock linux logo 2022-05-25 14:00:18 +02:00
Linus Dierheimer af4596b666 Bedrock linux 2022-05-25 13:59:40 +02:00
Linus Dierheimer 8c910089cc Detect KDE plasma version more reliable 2022-05-24 13:58:38 +02:00
Linus Dierheimer e79af7ba79 Relase 1.4.2
Bugfix: RPM package count on SUSE platforms
Bugfix: Prepend /var with TARGET_DIR_ROOT
2022-05-24 13:41:23 +02:00
Linus Dierheimer 960364bd47 Use librpm as rpm fallback 2022-05-24 13:36:33 +02:00
Linus Dierheimer ea44231c78 Don't prepend proc with TARGET_DIR_ROOT
Should make future packaging for termux simpler
2022-05-23 20:01:18 +02:00
Linus Dierheimer 60af0b9e39 Release 1.4.0
Feature: Display images converted to ascii art as logo, using chafa
Feature: Stretch images by using the --logo-height option
Logo: RedstarOS
Logo: Devuan
Logo: Rocky
Bugfix: Better calculation of image dimensions
Bugfix: Better rpm package detection
Bugfix: Format uptime right, when hours > 0 and minutes = 0
Bugfix: Only detect themes for installed gtk versions
2022-05-23 19:39:49 +02:00
Linus Dierheimer e4ecb9d069 Use sqlite to get rpm package count 2022-05-23 19:30:02 +02:00
Linus Dierheimer 3c648d84db Better GTK detection 2022-05-23 16:19:58 +02:00
Linus Dierheimer 45db4a5c3d Fix possible use after free 2022-05-23 15:50:25 +02:00
Linus Dierheimer caf976bec2 Fix building without chafa enabled 2022-05-23 15:36:19 +02:00
Linus Dierheimer b3d855355e Rewrote image dimension calculation 2022-05-23 15:32:10 +02:00
Linus Dierheimer 0a2eb49891 Merge pull request #164 from draumaz/master
Add Rocky Linux logo
2022-05-23 12:34:06 +02:00
draumaz ab2efa151a update readme 2022-05-23 03:29:04 -07:00
draumaz 1aee3f81c5 added Rocky Linux logo 2022-05-23 03:22:39 -07:00
Linus Dierheimer 4c7031cb12 Merge pull request #161 from Samisafool/patch-1
Typo
2022-05-16 11:51:08 +02:00
Samisafool 81c96d0f11 Typo 2022-05-16 09:54:48 +05:30
Linus Dierheimer 4d8680ec2d Merge pull request #160 from draumaz/master
Add Devuan logo
2022-05-15 23:46:56 +02:00
draumaz 039eb3a38a Fix alphabetical ordering 2022-05-15 13:48:10 -07:00
draumaz d07a653404 Update README.md 2022-05-15 13:45:31 -07:00
draumaz 76c0b7e457 Update README.md 2022-05-15 13:43:36 -07:00
draumaz 1c0e532b79 add Devuan 2022-05-15 06:22:28 -07:00
Linus Dierheimer c79a9f1bff Format uptime better 2022-05-14 14:13:10 +02:00
Linus Dierheimer 759069adfa Merge pull request #157 from Samisafool/patch-1
Fix bug_report.md
2022-05-14 14:03:04 +02:00
Samisafool 66ff6adfb0 Update bug_report.md 2022-05-13 14:06:05 +05:30
Samisafool 1dba19c49f Typo 2022-05-12 08:29:47 +05:30
Samisafool 2afd158d96 Fix bug_report.md 2022-05-12 08:28:24 +05:30
Linus Dierheimer 36c2ce6219 Look for newer versions of librpm 2022-05-05 15:48:01 +02:00
Linus Dierheimer 5f6432c150 RedstarOS logo 2022-05-04 18:11:32 +02:00
Linus Dierheimer e9f0eca3dd Add documentation about logo height option 2022-04-30 11:25:22 +02:00
Linus Dierheimer 998691847e logo-height option 2022-04-30 11:22:51 +02:00
Linus Dierheimer 64e5ef0df7 Fix output with no custom logo 2022-04-29 21:52:42 +02:00
Linus Dierheimer cc1e876faf Better automatic logo type detection 2022-04-29 21:44:32 +02:00
Linus Dierheimer 964a5aa8b4 Add chafa to feature list 2022-04-29 14:11:22 +02:00
Linus Dierheimer ad2601f097 Fix visual bug in README.md 2022-04-29 13:08:39 +02:00
Linus Dierheimer 7cae63ac05 Require chafa>=1.10 2022-04-29 13:07:20 +02:00
Linus Dierheimer 0d26cfb218 Dont try to build with ubuntu's outdated chafa enabled 2022-04-29 13:05:38 +02:00
Linus Dierheimer 3b6855b9da Build github packages with chafa support 2022-04-28 19:17:13 +02:00
Linus Dierheimer 51414c5511 Ascii image output using chafa 2022-04-28 19:15:46 +02:00
Linus Dierheimer 24f8ad7673 Release 1.3.4
* Bugfix: Using custom logos in terminals that don't support \033[14t or \033[18t once again works
* Feature: Ubuntu flavour detection
* Feature: Kubuntu logo
* Feature: Deepin logo
2022-04-27 08:03:15 +02:00
Linus Dierheimer e404dd62c0 Check for ubuntu flavours 2022-04-26 19:21:19 +02:00
Linus Dierheimer 21b315d548 Use a timeout when waiting for terminal responses 2022-04-26 17:17:16 +02:00
Linus Dierheimer 14fa052257 Use reasonable timeout for dbus 2022-04-25 18:42:05 +02:00
Linus Dierheimer 5861012d95 Deepin logo 2022-04-25 18:01:29 +02:00
Linus Dierheimer 4d9fbd93d2 Kubuntu logo 2022-04-25 17:51:51 +02:00
Linus Dierheimer 1d99bd2e08 Fix prebuild deb package for real this time 2022-04-23 11:28:46 +02:00
Linus Dierheimer 52eed51eb6 Fix prebuild deb package 2022-04-23 11:24:24 +02:00
Linus Dierheimer e5237c14cb Fix build without any image magick enabled 2022-04-22 21:29:14 +02:00
Linus Dierheimer 47d8ddad35 Release 1.3.0: Image support 2022-04-22 15:51:54 +02:00
Linus Dierheimer 37ab01d5ee Refactored some variable namings to reflect image support 2022-04-22 15:49:50 +02:00
Linus Dierheimer 80f7a982e0 Even faster image caching 2022-04-22 13:20:40 +02:00
Linus Dierheimer cff3aed49c RHEL logo 2022-04-21 18:07:39 +02:00
Linus Dierheimer 572d4ec8e9 NixOS support 2022-04-21 17:59:26 +02:00
Linus Dierheimer 5bceb29c79 Image caching 2022-04-21 15:50:45 +02:00
Linus Dierheimer 8b153833b1 Fallback to escape sequences if ioctl failed 2022-04-19 11:48:08 +02:00
Linus Dierheimer adc92b5548 Update packages.c 2022-04-19 00:32:28 +02:00
Linus Dierheimer 03e949ed30 Update DEVELOPMENT.md 2022-04-15 00:56:02 +02:00
Linus Dierheimer 6accb587af zlib support 2022-04-14 15:11:14 +02:00
Linus Dierheimer 373e041e5e Always dlclose when possible 2022-04-14 11:43:06 +02:00
Linus Dierheimer 31bdd25a26 Kitty graphics protocol support 2022-04-14 11:36:57 +02:00
Linus Dierheimer 703ec597fa Improved ImageMagick detection 2022-04-13 23:13:25 +02:00
Linus Dierheimer 3b1314102f Kitty graphics initial support 2022-04-13 23:04:42 +02:00
Linus Dierheimer d349b7f7fb Merge pull request #145 from Henryws/patch-1
fix(README): fix typo
2022-04-13 11:27:59 +02:00
The TwilightBlood dabdb104e2 fix(README): fix typo 2022-04-12 18:34:40 -05:00
Linus Dierheimer 8d5ce7bcdb Fix build when ImageMagick 6 enabled 2022-04-11 22:54:07 +02:00
Linus Dierheimer 751568e9f3 Faster fallback in sixel code 2022-04-11 22:51:51 +02:00
Linus Dierheimer 430fe9fe9a Avoid unnecessary cache validation 2022-04-11 18:54:56 +02:00
Linus Dierheimer 8831c07d2b Look for multiple versions of a library 2022-04-11 17:41:21 +02:00
Linus Dierheimer e009bb1516 Try with include math.h for ubuntu build 2022-04-11 16:39:56 +02:00
Linus Dierheimer 82e2790e1b Define isnan for imagemagick 6 2022-04-11 16:32:47 +02:00
Linus Dierheimer 64182539aa Support ImageMagick 6 too (this one is for you, Ubuntu) 2022-04-11 16:19:02 +02:00
Linus Dierheimer c67fd169f8 Refactor sixel code a bit 2022-04-10 22:08:41 +02:00
Linus Dierheimer f58d0df336 Default to termux directories on android 2022-04-10 15:26:18 +02:00
Linus Dierheimer bd0c593871 Simplify packaging for termux 2022-04-10 15:07:52 +02:00
Linus Dierheimer a032d37ad4 Refactored method naming / ordering 2022-04-08 15:50:49 +02:00
Linus Dierheimer a4861606b7 Small Sixel improvements 2022-04-06 14:54:39 +02:00
Linus Dierheimer 88fe34102e Only support ImageMagick 7 for now 2022-04-06 14:21:52 +02:00
Linus Dierheimer 5346104ffa Initial sixel support 2022-04-06 14:02:05 +02:00
Linus Dierheimer 12371cdc84 Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2022-04-02 14:44:44 +02:00
Linus Dierheimer 3248afe91c Prepare flashfetch for images in terminal too 2022-04-02 14:44:26 +02:00
Linus Dierheimer 1731ab2c5f Prepare for images in the terminal #2 2022-04-02 14:42:18 +02:00
Linus Dierheimer fcc8927917 Prepare for images in the terminal 2022-04-02 14:35:43 +02:00
Linus Dierheimer ccf4e2d2b5 OpenSUSE logos 2022-03-28 12:36:08 +02:00
Linus Dierheimer f2998a329d Add license info to rpm package 2022-03-25 12:24:56 +01:00
Linus Dierheimer 30365e8997 Release prebuild binaries as tar.gz and zip 2022-03-25 12:16:06 +01:00
Linus Dierheimer 5b66938bf4 Release with rpm package too 2022-03-25 12:09:48 +01:00
Linus Dierheimer 80c5600a7b Use cmake to build packages 2022-03-25 11:57:58 +01:00
Linus Dierheimer 65ce2eafed Hopefully finally fix github actions 2022-03-24 22:26:44 +01:00
Linus Dierheimer d840c7a12d Use workflow instead of action 2022-03-24 22:15:46 +01:00
Linus Dierheimer 634e27bc42 Try to give github actions the right permissions 2022-03-24 22:02:39 +01:00
Linus Dierheimer cc18315e84 Fix check action 2022-03-24 21:59:15 +01:00
Linus Dierheimer 83e2787b24 Use reusable action for check 2022-03-24 21:57:53 +01:00
Linus Dierheimer ef5a9384da Try to fix github actions again 2022-03-24 21:49:39 +01:00
Linus Dierheimer 2d7e6c37ff Try to fix github actions 2022-03-24 21:43:27 +01:00
Linus Dierheimer 92e8f23261 Refactored github actions again 2022-03-24 21:38:56 +01:00
Linus Dierheimer e09f1d3647 Refactored github actions 2022-03-24 21:32:45 +01:00
Linus Dierheimer 6f01e33955 Clear URL from unsucessfull media detection too 2022-03-24 19:06:20 +01:00
Linus Dierheimer 4b813cdf59 Automatic track commits between versions 2022-03-24 18:56:44 +01:00
Linus Dierheimer 942c583c89 Media: Don't show website urls 2022-03-23 21:41:52 +01:00
Linus Dierheimer 24a48c1fc0 Dont show lyric information in song title 2022-03-23 16:07:47 +01:00
Linus Dierheimer e2e95732e8 Don't remove dirty / clean from song title 2022-03-23 15:58:30 +01:00
Linus Dierheimer d647f9e3f2 Pretty song output, if the media is a browser playing a video 2022-03-23 15:43:30 +01:00
Linus Dierheimer 4895c68ca9 Capitalize the first letter of media player if appropiate 2022-03-23 11:54:05 +01:00
Linus Dierheimer f0b9800974 Fix fastfetch recaching every time if an old cache exists 2022-03-23 11:38:42 +01:00
Linus Dierheimer be84549f4c Refactored media detection 2022-03-23 11:15:50 +01:00
Linus Dierheimer 0916258c87 Greatly improved detection of media player name 2022-03-22 18:59:04 +01:00
Linus Dierheimer ad006b466c Version output include extra info 2022-03-20 17:12:52 +01:00
Linus Dierheimer efdf38a9ea Version 1.0.0 ! 2022-03-20 16:47:05 +01:00
Linus Dierheimer 10a202fe80 First Release? v14 2022-03-20 16:44:08 +01:00
Linus Dierheimer 6e8aca0945 First Release? v13 2022-03-20 16:37:27 +01:00
Linus Dierheimer 4cd08b82d4 First Release? v12 2022-03-20 16:32:15 +01:00
Linus Dierheimer a2ebecdf6d First Release? v11 2022-03-20 16:28:57 +01:00
Linus Dierheimer aa352a4427 First Release? v10 2022-03-20 16:23:25 +01:00
Linus Dierheimer 10c97aea4b First Release? v9 2022-03-20 16:22:27 +01:00
Linus Dierheimer e08cb24cb5 First Release? v8 2022-03-20 16:08:20 +01:00
Linus Dierheimer bfbaecb533 First Release? v7 2022-03-20 16:01:31 +01:00
Linus Dierheimer d915f415b1 First Release? v6 2022-03-20 15:57:59 +01:00
Linus Dierheimer 1887e21ddc First Release? v5 2022-03-20 15:53:08 +01:00
Linus Dierheimer 0b6c974126 First Release? v4 2022-03-20 15:45:22 +01:00
Linus Dierheimer fdd8919e1c First Release? v3 2022-03-20 15:43:21 +01:00
Linus Dierheimer 0c936cab27 First Release? v2 2022-03-20 15:42:37 +01:00
Linus Dierheimer d17aae5d65 First Release? 2022-03-20 15:40:23 +01:00
Linus Dierheimer 77e05b0c95 prepare for releases 2022-03-20 13:16:04 +01:00
Linus Dierheimer 0f6e266fc3 Removed unneeded else 2022-03-17 16:52:19 +01:00
Linus Dierheimer de779cf1ea Create FUNDING.yml 2022-03-17 16:35:34 +01:00
Linus Dierheimer ecbb854e54 KDE Neon logo 2022-03-15 18:49:44 +01:00
Linus Dierheimer da26a3497e Update README.md 2022-03-15 11:13:15 +01:00
Linus Dierheimer a6770581d3 Easter egg for uptime >= 100 days
Similiar to htop
2022-03-14 18:02:03 +01:00
Linus Dierheimer 07a685bb9a 16 Colors in TTY 2022-03-14 17:31:16 +01:00
Linus Dierheimer 00fdb8a0c4 Generic Linux logo 2022-03-09 17:39:36 +01:00
shivanandvp 4e68c09f27 Adding RebornOS to the supported logos (#140)
* feat: Add logos for RebornOS

* feat: Decrease the size of the RebornOS logo and prepare a better small RebornOS logo

* fix: Align text for both the regular and small RebornOS logos
2022-03-08 18:39:23 +01:00
Linus Dierheimer b5a36b0825 Update README.md 2022-03-08 12:13:01 +01:00
Linus Dierheimer 231016264b Update CMakeLists.txt 2022-03-08 12:03:21 +01:00
Linus Dierheimer 0451852e34 Install License with cmake too 2022-03-08 11:59:06 +01:00
Linus Dierheimer b9dfe1f858 Fix compilation warnings 2022-03-08 11:07:31 +01:00
Linus Dierheimer 51bbff4741 Zorin Logo 2022-03-08 10:47:04 +01:00
Linus Dierheimer 7c9b5c2c61 Update datetime.c 2022-02-25 15:06:24 +01:00
Linus Dierheimer fd450bcccc Date Time support 2022-02-25 13:30:37 +01:00
Linus Dierheimer 0cb6e40bac Fix neofetch preset 2022-02-21 14:44:46 +01:00
Linus Dierheimer 9c20c50c3d Merge pull request #136 from CyberTailor/master
CMake improvements
2022-02-21 14:40:41 +01:00
Anna “CyberTailor” aa9dd9c155 CMakeLists.txt: make tests optional
Run test-strbuf using ctest.
2022-02-21 12:30:06 +05:00
Anna “CyberTailor” 415c097489 CMakeLists.txt: use git only when in repository
Allow building fastfetch from tarballs with -DPROJECT_VERSION and
-DPROJECT_VERSION_MAJOR options.
2022-02-21 12:30:06 +05:00
Anna “CyberTailor” 109026211c CMakeLists: add installation target 2022-02-21 12:30:05 +05:00
Linus Dierheimer ed63ef1a28 Support detecting artist if a browser is current media player 2022-02-14 13:04:57 +01:00
Linus Dierheimer f54ac1c4e6 Update tests 2022-02-14 12:04:54 +01:00
Linus Dierheimer 313084f91c Update presets 2022-02-14 11:44:10 +01:00
Linus Dierheimer 59bd9927a4 Fix concating of song artists 2022-02-14 11:08:04 +01:00
Linus Dierheimer e2be34e23d Update DEVELOPMENT.md 2022-02-14 01:12:26 +01:00
Linus Dierheimer 3ca3687993 Update README.md 2022-02-14 00:48:35 +01:00
Linus Dierheimer c066446685 Update GitHub Actions again 2022-02-14 00:43:56 +01:00
Linus Dierheimer ecb38e8d20 Update GitHub Actions 2022-02-14 00:41:11 +01:00
Linus Dierheimer c800077b73 Fix GitHub actions once again 2022-02-14 00:35:54 +01:00
Linus Dierheimer fcea3649e2 Fix GitHub actions again 2022-02-14 00:29:54 +01:00
Linus Dierheimer eaaa2705d3 Fix GitHub actions 2022-02-14 00:25:51 +01:00
Linus Dierheimer a32b1c5887 Update github actions to support song and media player update 2022-02-14 00:18:22 +01:00
Linus Dierheimer cfb5d204a1 Media player and song detection! 2022-02-13 23:51:13 +01:00
Linus Dierheimer d6ae32374e Update DEVELOPMENT.md 2022-02-13 13:26:00 +01:00
Linus Dierheimer 451848f6fd Small improvements to code quality 2022-02-12 22:30:57 +01:00
Linus Dierheimer a7728f61fb Battery: show full status 2022-02-12 18:20:00 +01:00
Linus Dierheimer fb3028cafa Update DEVELOPMENT.md 2022-02-12 12:45:00 +01:00
Linus Dierheimer ea5b663b16 Rename class to deviceClass, so cpp linters don't see a problem 2022-02-12 12:38:14 +01:00
Linus Dierheimer 9659f8c7b1 Add AUR packaging as submodul 2022-02-12 12:31:42 +01:00
Linus Dierheimer 3f64ef0876 Show emerge packages earlier in list 2022-02-12 12:13:02 +01:00
Linus Dierheimer 8c6cb9405d Use FFstrbuf in emerge package counting 2022-02-12 12:06:16 +01:00
Viorel 8a754f5b89 Add packages support for Gentoo Linux (#131)
Count packages installed by Gentoo emerge
2022-02-12 11:16:14 +01:00
Linus Dierheimer 5f965ac787 Fixed two compiler warnings 2022-02-09 15:22:57 +01:00
Linus Dierheimer bc8887fb42 Improved compile time by compiling common sources as a static lib 2022-02-09 15:20:07 +01:00
Linus Dierheimer 2ff3595251 Update DEVELOPMENT.md 2022-02-09 11:14:20 +01:00
Linus Dierheimer 47a58ad7b5 Update build-deb-package.yml 2022-02-08 19:30:55 +01:00
Linus Dierheimer ec523e0274 Update DEVELOPMENT.md 2022-02-08 19:28:05 +01:00
xzvf 87e410e0fc Add a Github Action to build and package fastfetch for Debian. (#127)
* Create a build.yml file

* add debian packaging

untested

* Copy & Paste is hard

* Fix typo, libRpm -> librpm

* Change working-dir

* Try again. Maybe now it will find the deb package

* Add more dependencies

* This should be it, hopefully

* Fix installed packages

* Change the name of the auto-created releases

* Document GH action

* Remove unnecessary packages. 

Apparently brute-forcing dependencies until the build is successful is not a good strategy.

* Move building the packaging into a seperate github action.

* Remove packaging from test Action
2022-02-08 19:15:28 +01:00
Linus Dierheimer cc43ed2351 Merge pull request #130 from ceamac/features/cmake/options
Make dependencies check optional
2022-02-08 11:51:08 +01:00
Viorel a28c4600f4 Make dependencies check optional 2022-02-08 07:10:46 +02:00
Linus Dierheimer 7ad73d3ba1 Fix arco linux logo 2022-01-29 10:32:23 +01:00
Linus Dierheimer f72ec8a99f Updated screenshot 2022-01-23 13:54:56 +01:00
Linus Dierheimer 6107241f4a Update README.md 2022-01-23 12:08:58 +01:00
Linus Dierheimer 68e8ddce6f Update README.md 2022-01-23 12:07:49 +01:00
Linus Dierheimer 1a57d82675 Update README.md 2022-01-23 12:07:04 +01:00
Linus Dierheimer c662416b33 Update README.md 2022-01-23 12:02:26 +01:00
Linus Dierheimer 79331d7fe5 Update README.md 2022-01-23 12:00:28 +01:00
Linus Dierheimer e887b56209 Fix performance test 2022-01-22 23:03:09 +01:00
Linus Dierheimer 23b71cc907 Fixed some rare compilation warnings from old compilers 2022-01-22 23:01:09 +01:00
Linus Dierheimer 4e45a2e3ba Fix building with librpm support enabled 2022-01-22 22:54:20 +01:00
Linus Dierheimer 14115eb089 Merge pull request #123 from x-zvf/master
Add packaging for Debian based distributions.
2022-01-22 13:11:41 +01:00
xzvf 8f466735a8 Add .deb file and deb-package build directory to .gitignore 2022-01-22 12:40:58 +01:00
xzvf 7a7eac9edd Copy presets to /usr/share/fastfetch/presets 2022-01-22 12:40:10 +01:00
xzvf 65dc9bb166 Remove flashfetch target, and fix 2 shellcheck warnings 2022-01-22 12:35:21 +01:00
xzvf (Péter Bohner) 57ef794864 Add packaging for Debian based distributions.
This commit adds a script (`create-deb-pkg.sh`), which creates a deb package containing the fastfetch and flashfetch executables as well as the bash-completion file. The script must be executed in an environment, where `dpkg-deb` is present (a debian based environment).
Because Deb versioning is not compatible with fastfetch version strings, it is adapted to the format: `0:1$FF_VERSION-0`.
2022-01-22 11:56:11 +01:00
Linus Dierheimer cd4739e4f7 Merge pull request #122 from TahaAbbasi-Hashemi/master
Artix_small logo had an extra space in line4
2022-01-20 15:25:02 +01:00
Taha Abbasi-Hashemi 3a667add01 Artix_small logo had an extra space in line4 2022-01-20 09:10:01 -05:00
Linus Dierheimer 6906094b8b Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2022-01-20 12:19:18 +01:00
Linus Dierheimer b8a239e379 Add endeavour logo 2022-01-20 12:18:56 +01:00
Linus Dierheimer e30a64e97e Update README.md 2022-01-20 01:22:13 +01:00
Linus Dierheimer f2663a65cc More flexible OS file detection 2022-01-18 18:56:37 +01:00
Linus Dierheimer a0f5432903 Temp detection 2022-01-16 16:33:15 +01:00
Linus Dierheimer 20427a534e Respect WAYLAND_SOCKET on builds without wayland-client support 2022-01-14 13:31:39 +01:00
Linus Dierheimer 9789d1f5f1 Fallback OS detection using lsb 2022-01-14 13:21:49 +01:00
Linus Dierheimer bf2152bac8 Disable public ip timeout by default 2022-01-12 19:16:49 +01:00
Linus Dierheimer accaaa7de5 Expose GPU driver to gpu format string 2022-01-12 18:57:35 +01:00
Linus Dierheimer 322e5c5a48 FFstrbuf: don't do unneeded destroy work 2022-01-12 02:05:12 +01:00
Linus Dierheimer 6d7ad48edf Clear destroyed FFstrbuf 2022-01-12 01:59:57 +01:00
Linus Dierheimer 6a62f909d4 Destroyed FFstrbufs can now be reused 2022-01-12 01:57:49 +01:00
Linus Dierheimer 3653836490 Merge pull request #119 from CachyOS/master
Add CachyOS logo support
2022-01-12 01:52:15 +01:00
Linus Dierheimer f21013f646 Use same variable name in definition and declaration 2022-01-12 01:33:03 +01:00
Linus Dierheimer 8639e59019 Silence a false positive compiler warning 2022-01-12 01:21:36 +01:00
Linus Dierheimer 33127388f0 refactored FFstrbuf 2022-01-12 01:02:14 +01:00
Vladislav Nepogodin f54101e9f5 🔥 add cachyos 2022-01-12 01:17:23 +04:00
Vladislav Nepogodin d79b7a8944 🔥 add cachyos 2022-01-12 01:11:58 +04:00
Vladislav Nepogodin 2c7314dd8e 🔥 add cachyos logo 2022-01-12 01:10:04 +04:00
Linus Dierheimer 729d9d5c47 Add help for IP format 2022-01-11 12:36:32 +01:00
Linus Dierheimer 1c72219a88 Fix ordering of macros in settings.c 2022-01-10 20:45:58 +01:00
Linus Dierheimer 816d86aee8 Public IP module 2022-01-10 20:20:18 +01:00
Linus Dierheimer d6a80d7c85 Android support part 7 2022-01-10 15:31:36 +01:00
Linus Dierheimer ef034b7adb Android support part 6 2022-01-10 15:26:25 +01:00
Linus Dierheimer 4bbb13b44d Android support part 5 2022-01-10 15:24:10 +01:00
Linus Dierheimer 4aff8a353b Android support part 4 2022-01-10 15:22:25 +01:00
Linus Dierheimer 190974e079 Android support part 3 2022-01-10 15:20:51 +01:00
Linus Dierheimer e95e1e3530 Android support part 2 2022-01-10 14:41:34 +01:00
Linus Dierheimer 1d6119f858 Update DEVELOPMENT.md 2022-01-09 19:49:19 +01:00
Linus Dierheimer bf60429e36 Android support part 1 2022-01-09 16:51:57 +01:00
Linus Dierheimer 31d0729cdd Small syntactic changes 2022-01-08 21:58:37 +01:00
Linus Dierheimer 0879746e0f Unified method for testing if c strings contain a value 2022-01-07 18:00:38 +01:00
Linus Dierheimer 3f30fa8d4a Improved WM / DE detection logic 2022-01-07 17:37:57 +01:00
Linus Dierheimer 53f31f2401 Look for different versions of the same library 2022-01-05 16:14:27 +01:00
Linus Dierheimer 59e61f53e1 XCB: set wm protocol if connection succeded 2022-01-05 15:02:54 +01:00
Linus Dierheimer 7a3bf2f77d Rewrote X11 code 2022-01-05 14:40:57 +01:00
Linus Dierheimer bd3a5fde07 Finish rewriting of WM/DE detection 2022-01-02 19:02:21 +01:00
Linus Dierheimer ecb1853d56 Using EWMH to detect WM in X11 sessions 2022-01-02 18:42:58 +01:00
Linus Dierheimer bcf543e129 Unified WM / DE / Resolution detection 2022-01-02 16:55:26 +01:00
Linus Dierheimer 06fa8e7478 Use ffStrbufEndsWithC instead of custom impl 2022-01-01 17:28:41 +01:00
Linus Dierheimer f73137aef8 Better filtering of batteries 2021-12-31 14:12:44 +01:00
Linus Dierheimer d4f753a9f8 Moved detection files to their own folder 2021-12-20 16:34:46 +01:00
Linus Dierheimer 65bac0efc9 Color name mapping 2021-12-20 12:12:55 +01:00
Linus Dierheimer a15b3661c3 Flashfetch: don't print cpu usage and local ip by default 2021-12-19 22:52:16 +01:00
Linus Dierheimer a011b55692 Custom logo colors support 2021-12-19 22:39:22 +01:00
Linus Dierheimer 87eb2659de Create codeql-analysis.yml 2021-12-15 22:18:35 +01:00
Linus Dierheimer 1a7f04fe0c Suppress the output of drivers more efficently 2021-12-15 19:12:07 +01:00
Linus Dierheimer 7638d0b8b6 Disable stdout during vulkan operations 2021-12-15 15:42:33 +01:00
Linus Dierheimer b89e41c1d7 Updated GitHub bug report template 2021-12-13 18:19:12 +01:00
Linus Dierheimer 809f9310a5 Updated DEVELOPMENT.md 2021-12-10 15:58:34 +01:00
Linus Dierheimer 9b7f236397 Update DEVELOPMENT.md 2021-12-09 13:27:36 +01:00
Linus Dierheimer 8f865cf823 Update DEVELOPMENT.md 2021-12-09 12:04:04 +01:00
Linus Dierheimer dedbd5b529 Update DEVELOPMENT.md 2021-12-07 17:46:44 +01:00
Linus Dierheimer 5f178880c7 updated DEVELOPMENT:md 2021-12-07 17:42:57 +01:00
Linus Dierheimer 74b809f68a removed obsolete function 2021-12-07 17:21:25 +01:00
Linus Dierheimer f0732d0056 small cleanup 2021-12-07 17:20:11 +01:00
Linus Dierheimer e6851eeabc Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2021-12-06 20:04:03 +01:00
Linus Dierheimer 9e2d6be31f Removed zsh completion stub 2021-12-06 20:03:53 +01:00
Linus Dierheimer 7f846dadaf Fix --logo option when using not existent file 2021-12-06 20:03:17 +01:00
Linus Dierheimer 79bec5c220 Merge pull request #112 from CarterLi/master
CPU Usage: add new module
2021-11-24 12:17:05 +01:00
Carter Li 8653a881fd CPU Usage: add new module 2021-11-24 19:14:27 +08:00
Linus Dierheimer aaa6f32f15 updated .editorconfig 2021-11-19 12:42:03 +01:00
Linus Dierheimer bbbf00e834 Separator string option 2021-11-18 18:25:24 +01:00
Linus Dierheimer 7bab4ef298 Fix disk space output 2021-11-17 23:22:42 +01:00
Linus Dierheimer 9db9a2c195 Added -Wconversion to compiler options 2021-11-17 18:38:57 +01:00
Linus Dierheimer cb16cd583b Orderd arco linux logo method alphabetically 2021-11-17 12:09:55 +01:00
Linus Dierheimer 2abaf64c12 fix a compiler warning in ffStrbufEnsureCapacity 2021-11-17 12:07:08 +01:00
Linus Dierheimer 4e818c981a Found a better way to fix the warning from pevious commit 2021-11-17 12:00:06 +01:00
Linus Dierheimer 6c4961aaff Fix a wrong compiler warning in io.c 2021-11-17 11:57:50 +01:00
Linus Dierheimer 7db781c508 Fix possible seg fault in ffStrbufAppendVF 2021-11-17 11:41:17 +01:00
Linus Dierheimer 7ced537e59 FFstrbuf is now always null terminated 2021-11-17 10:59:31 +01:00
Linus Dierheimer f0e623c3de Remove unnecesarry strbuf allocation 2021-11-16 13:05:02 +01:00
Linus Dierheimer 40d535ffba Allow 0 length FFstrbuf 2021-11-16 12:54:49 +01:00
Linus Dierheimer 18bfc6bd11 Merge pull request #110 from Rayrsn/master
Add Arco Linux logo support
2021-11-16 10:48:03 +01:00
Rayr 6823b65615 Added Arco Linux logo 2021-11-16 00:19:50 +03:30
Rayr ad347a6083 Update README.md 2021-11-16 00:19:37 +03:30
Rayr fff69ac7e2 Update README.md 2021-11-16 00:18:53 +03:30
Rayr d41d31a6a7 Added Arco Linux logo 2021-11-16 00:18:20 +03:30
Linus Dierheimer 9e6b0b03ea Tell vulkan the right project version 2021-11-13 18:43:33 +01:00
Linus Dierheimer dff3ca58ae GPU: vulkan fallback 2021-11-13 18:25:35 +01:00
Linus Dierheimer fc77e40ea9 Added dwm to list of known window managers 2021-11-13 16:57:59 +01:00
Linus Dierheimer 869aa67d1f Fix font detection on plasma 5.23+ 2021-11-13 16:46:32 +01:00
Linus Dierheimer fd447ab439 Common macros for loading shared libs 2021-11-13 14:10:30 +01:00
Linus Dierheimer 6cdf32dabc Small variants of logos 2021-11-12 01:39:21 +01:00
Linus Dierheimer 1c8eca1010 Logo printing: keep state and config separate 2021-11-11 19:10:52 +01:00
Linus Dierheimer 42b8182428 Added linux mint old logo 2021-11-10 14:03:11 +01:00
Linus Dierheimer e54398f7b3 Fix autocompletion of logos 2021-11-09 16:53:08 +01:00
Linus Dierheimer 27334f77cc Remove outdated section from DEVELOPMENT.md 2021-11-09 15:20:54 +01:00
Linus Dierheimer 6b0343a46c Merge branch 'master' of remote 2021-11-09 15:18:02 +01:00
Linus Dierheimer 214540e7ef Logo revolution 2021-11-09 15:14:25 +01:00
Linus Dierheimer 0c7a415f9b librpm: don't print error messages 2021-11-08 11:50:50 +01:00
Linus Dierheimer 0048c1ca98 Merge pull request #106 from CarterLi/master
Add CentOS logo support
2021-11-08 11:08:06 +01:00
Carter Li df2ad48d13 Logo: add CentOS logo 2021-11-08 17:37:17 +08:00
Carter Li a81f897258 CMakeList: don't require C++ compilers 2021-11-08 10:28:48 +08:00
Linus Dierheimer e9db9ac87a Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2021-11-07 21:36:08 +01:00
Linus Dierheimer a198322d58 logo part 1 2021-11-07 21:35:59 +01:00
Linus Dierheimer 6e6086a8b4 Merge pull request #105 from CarterLi/master
Packages: use the official librpm instead of libsqlite3
2021-11-07 21:23:32 +01:00
李通洲 b3b31d693e Settings: simplify macros and code cleanup 2021-11-06 22:50:52 +08:00
李通洲 f6700f5272 Packages: use the official RPM public API
instead of diving into its implementation detail to count installed rpm packages, which support CentOS
2021-11-06 22:47:51 +08:00
Linus Dierheimer 58ec50fa7f Merge pull request #103 from Linus789/preset-neofetch-fix
Make the preset neofetch more like neofetch
2021-11-03 18:23:05 +01:00
Linus789 15328345da Make the preset neofetch more like neofetch
- os-format: Print architecture without square brackets
- resolution-format: Do not print the refresh rate
- de-format: Use pretty name and print version
- theme-format: Print color scheme without brackets
- memory-format: Use MiB instead of Mib
2021-11-03 17:46:29 +01:00
Linus Dierheimer 0f16bf2698 Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2021-11-01 19:39:05 +01:00
Linus Dierheimer 46ecdd42b6 Development notice 2021-11-01 19:37:45 +01:00
Linus Dierheimer 7663637ea9 Development notice 2021-11-01 19:33:12 +01:00
Linus Dierheimer bf1fbd572a Fix display of long terminal names 2021-11-01 14:47:36 +01:00
Linus Dierheimer e3f0319575 Merge pull request #102 from NBonaparte/master
fix: check if `processName` is NULL/empty to prevent segfaults
2021-11-01 12:32:33 +01:00
NBonaparte f333ede1f7 fix: check if processName is NULL/empty to prevent segfaults 2021-10-31 22:13:29 -07:00
Linus Dierheimer c0584cf465 More options documented in config file 2021-10-31 12:12:51 +01:00
Linus Dierheimer 00c05f14c7 Update bug_report.md 2021-10-25 13:34:43 +02:00
Linus Dierheimer c008f66a76 Fix bug in terminal format 2021-10-25 13:31:25 +02:00
Linus Dierheimer 57377019e6 Verbose and devinfo presets 2021-10-25 13:29:39 +02:00
Linus Dierheimer 2f555df690 Update issue templates 2021-10-24 21:25:10 +02:00
Linus Dierheimer eb6b8778b3 Update issue templates 2021-10-24 21:20:58 +02:00
Linus Dierheimer 09285338c5 Fix possible unassigned variable in memory code 2021-10-24 15:11:17 +02:00
Linus Dierheimer 20dd2fa28f New fedora logo 2021-10-24 14:47:28 +02:00
Linus Dierheimer 7a21f44a3a Exit signal handler 2021-10-23 15:48:24 +02:00
Linus Dierheimer 1df591b46f More informations in default config file 2021-10-23 14:59:11 +02:00
Linus Dierheimer b3ef53ddc9 Store big strings in separate files 2021-10-22 21:53:29 +02:00
Linus Dierheimer e18199e8ec Fix odering of XDG_CONFIG_DIRS 2021-10-22 18:42:14 +02:00
Linus Dierheimer 3923f11a45 Merge pull request #100 from CarterLi/master
Fix double free memory error
2021-10-20 18:48:07 +02:00
李通洲 c223ace5eb Fix double free memory error 2021-10-21 00:41:35 +08:00
Linus Dierheimer 9b399da872 Merge pull request #99 from CarterLi/master
Add Android basic support
2021-10-20 16:31:11 +02:00
李通洲 1a5b1428dc Add Android basic support 2021-10-20 22:27:29 +08:00
Linus Dierheimer 5589293d76 Merge pull request #98 from CarterLi/cmake
CMakeList: cleanup
2021-10-20 15:19:35 +02:00
李通洲 714181175d CMakeList: cleanup
Default CMAKE_BUILD_TYPE to Release, which implies -O3 -DNDEBUG
Don't force building with -O3, which makes debugging more friendly.
Remove option BUILD_DEBUG, which is covered by -DCMAKE_BUILD_TYPE=DEBUG / RelWithDebInfo
2021-10-20 08:13:49 +00:00
Linus Dierheimer fd257ddde9 better FF_UNUSED 2021-10-19 19:34:55 +02:00
Linus Dierheimer 349e5b24fa better support for building without features 2021-10-19 18:44:59 +02:00
Linus Dierheimer 73436824f9 Merge pull request #96 from CarterLi/build
Make it possible to build without optional dependencies
2021-10-19 17:07:25 +02:00
李通洲 e5322cf165 Make it possible to build without optional dependencies 2021-10-19 22:50:17 +08:00
Linus Dierheimer 564ddfc1b6 Merge pull request #95 from CarterLi/master
Add a new module that shows the number of current running processes
2021-10-19 15:07:12 +02:00
李通洲 181dfb5cfc Processes: add new module 2021-10-19 02:25:34 +00:00
Linus Dierheimer 072a4bc412 Merge pull request #94 from yuannan/master
Multithreading make
2021-10-18 16:47:38 +02:00
yuannan 914cd9219d tests multithreading 2021-10-18 02:40:33 +01:00
yuannan dbc4a815c5 updated building instructions 2021-10-18 02:23:02 +01:00
yuannan 5d97436c7d multithreading make 2021-10-18 02:18:42 +01:00
Linus Dierheimer 5f0c5a0351 Merge pull request #91 from CarterLi/master
Fix detecting Windows Terminal on WSL2
2021-10-17 15:17:32 +02:00
李通洲 7dc70b9730 Fix detecting Windows Terminal on WSL2 and SSH env 2021-10-17 21:12:19 +08:00
Linus Dierheimer d288a698b0 Merge pull request #92 from CarterLi/localip
Add new module that shows local IP addresses which are useful with frontend development
2021-10-17 15:09:26 +02:00
李通洲 38e2f8cf3e LocalIp: add new module 2021-10-17 21:05:04 +08:00
Linus Dierheimer 0b3f96610b Merge pull request #93 from CarterLi/wsl2
Better support devices running without desktop environment ( and WSL2 ), fix #83
2021-10-17 14:33:24 +02:00
李通洲 3a649493ea Don't print error: XDG_RUNTIME_DIR not set in the environment. when $XDG_RUNTIME_DIR is not set
According to [the manpage](https://manpages.debian.org/experimental/libwayland-doc/wl_display_connect.3.en.html), $XDG_RUNTIME_DIR must be set before calling `wl_display_connect(NULL)`.
Otherwise `wl_display_connect` will always fail, and print the error message
2021-10-17 18:37:51 +08:00
李通洲 8d7d33882f Always assume TTY when both $XDG_SESSION_TYPE and $WAYLAND_DISPLAY are not set
$TERM can be set to value other than `linux` ( eg xterm, xterm-256color ), just assume TTY when no desktop env is found, which effectively bypasses `getWMDE`
Fix #83
2021-10-17 18:34:11 +08:00
Linus Dierheimer f265307dc4 Prefer process name in terminal output 2021-09-19 14:58:46 +02:00
Linus Dierheimer e02d81d866 Merge pull request #81 from halfhiddencode/patch-1
Update logo.c
2021-07-31 09:52:39 +02:00
halfhiddencode a2742ce60b Update logo.c
correction in garuda logo
2021-07-18 08:16:23 +00:00
Linus Dierheimer 588a68ac4c Better OS output 2021-07-12 19:01:31 +02:00
Linus Dierheimer 0f916bb492 Better ffParseSemver 2021-07-08 20:02:53 +02:00
Linus Dierheimer 9faf664320 Merge pull request #77 from BL4CKH47H4CK3R/patch-1
Beautify Arch Logo
2021-07-06 22:10:02 +02:00
BL4CKH47H4CK3R 7fa971bc86 Beautify Arch Logo 2021-07-06 19:49:27 +00:00
Linus Dierheimer b733bb628d Update README.md 2021-07-06 21:25:12 +02:00
Linus Dierheimer d7356a8323 Cleand up resolution code 2021-07-06 21:15:08 +02:00
Linus Dierheimer 26f4fac62b feature request #75: CelOS logo 2021-07-06 20:36:30 +02:00
Linus Dierheimer 273d4205b5 Xrandr: support for multiple output monitors 2021-07-05 20:59:58 +02:00
Linus Dierheimer 1717b51807 fix compiler warning about unused result of fscanf 2021-07-02 23:07:25 +02:00
Linus Dierheimer 7b5af1b133 Rewrote x11 resolution detection 2021-07-02 22:43:58 +02:00
Linus Dierheimer 45e5546c92 Don't show certain informations in TTY 2021-06-27 21:53:50 +02:00
Linus Dierheimer 8f1b067953 fix resolution in x11 / TTY 2021-06-27 21:43:09 +02:00
Linus Dierheimer ad220546ba small cleanup in cursor code 2021-06-27 21:18:43 +02:00
Linus Dierheimer 78af5cb8a8 better resolution detection 2021-06-27 21:09:18 +02:00
Linus Dierheimer dc2f45626f Merge pull request #72 from DarNCelsius/master
Clean up cursor.c
2021-06-26 19:13:39 +02:00
DarN 4d408f55fa Optimisation 2021-06-26 19:00:15 +02:00
Linus Dierheimer 3f936e084d Merge pull request #71 from DarNCelsius/master
LXQT cursor support
2021-06-26 18:35:02 +02:00
DarN 764d2b7fc9 Refactored config file cursor functions 2021-06-26 18:14:09 +02:00
DarN 11c07d6738 LXQT cursor support 2021-06-26 17:31:50 +02:00
Linus Dierheimer 262a3eb59f remove trailing - in cursor output 2021-06-26 17:08:15 +02:00
Linus Dierheimer 0d09b89016 Merge pull request #70 from DarNCelsius/master
Sanitize custom Plasma theme name
2021-06-26 16:54:49 +02:00
DarN d2156dfc1d Remove fluff 2021-06-26 16:53:43 +02:00
Linus Dierheimer 2c599b5924 prettier cursor output 2021-06-26 16:48:15 +02:00
DarN 3d3216ba91 Added flexible remove logic 2021-06-26 16:47:47 +02:00
DarN d7a8623f90 Merge branch 'LinusDierheimer:master' into master 2021-06-26 16:07:32 +02:00
Linus Dierheimer 582d5b6473 better naming of strbuf methods 2021-06-26 15:34:01 +02:00
Linus Dierheimer 19b71d9ce0 change cursor size from pt to px 2021-06-26 11:43:36 +02:00
Linus Dierheimer a88cb07dad better cursor support 2021-06-26 11:39:42 +02:00
DarN 4c02b8319b Comment edit 2021-06-26 08:40:23 +02:00
DarN ea8c68bab4 Sanitize custom Plasma theme name 2021-06-26 08:14:11 +02:00
Linus Dierheimer d4d9bc90e6 fix cursor detection in xfce 2021-06-20 22:26:06 +02:00
Linus Dierheimer c0cb55ca9a fix ffParsePropFileConfigValues 2021-06-20 22:17:18 +02:00
Linus Dierheimer 8cb3ff7c2b Cursor support 2021-06-20 21:04:55 +02:00
Linus Dierheimer ef31e08d2d Allow same GTK values in same file to overwrite each other 2021-06-17 13:59:18 +02:00
Linus Dierheimer f148dbacfb Disable linewrap and hide cursor by default 2021-06-17 13:49:25 +02:00
Linus Dierheimer 450ac7f2cd simplified host code 2021-06-16 12:20:56 +02:00
Linus Dierheimer 98f420ad3d handle cpu frequencies right 2021-06-16 11:47:32 +02:00
Linus Dierheimer 27915127a8 improved cpu detection 2021-06-16 11:28:33 +02:00
Linus Dierheimer ea2f6470d8 improved host detection 2021-06-16 10:50:16 +02:00
Linus Dierheimer 9ade52ddc0 Added "Default string" to not allowed host values 2021-06-15 18:12:33 +02:00
Linus Dierheimer 409b1f29a6 renamed calculation threads to detection threads 2021-06-15 13:12:29 +02:00
Linus Dierheimer f8c215775a better zsh and fish version detection 2021-06-15 12:35:44 +02:00
Linus Dierheimer 0bf486fa67 seperator is now always the width of the title 2021-06-15 11:04:44 +02:00
Linus Dierheimer 4fecc76083 specific fish version code 2021-06-15 09:51:55 +02:00
Linus Dierheimer 2bae720e00 removed unnecessary code 2021-06-15 09:27:53 +02:00
Linus Dierheimer bfd76ae455 merge 2021-06-15 09:24:14 +02:00
Linus Dierheimer cab5069be2 fix terminal / shell detection 2021-06-15 09:23:37 +02:00
Linus Dierheimer 5aa5ab2c16 fix terminal / exe detection 2021-06-15 09:21:38 +02:00
Linus Dierheimer 5515eea42d merging 2021-06-14 23:22:44 +02:00
Linus Dierheimer eab26149e7 rewrote shell / terminal detection 2021-06-14 23:22:14 +02:00
Linus Dierheimer d77fc9a9c3 Merge pull request #65 from wizard-28/Code-Quality
Improved code quality
2021-06-14 11:44:28 +02:00
Sourajyoti Basak 0108a3ade0 Revert headers 2021-06-14 14:57:45 +05:30
Sourajyoti Basak e79209c7bf Change shebang 2021-06-14 14:22:51 +05:30
Sourajyoti Basak 399eee1963 Change shebang 2021-06-14 14:22:28 +05:30
Sourajyoti Basak 4f2b3d740e Update run.sh 2021-06-14 12:19:21 +05:30
Sourajyoti Basak bc65c9f9c3 Add shebang 2021-06-14 12:18:39 +05:30
Sourajyoti Basak 756593e160 Fix heading increment 2021-06-14 12:12:17 +05:30
Sourajyoti Basak ed3e5b544f Fix heading punctuation 2021-06-14 12:09:18 +05:30
Sourajyoti Basak 7b58c97ff3 Fix list item idents 2021-06-14 12:07:08 +05:30
Linus Dierheimer ab2cb9e0e4 fix gentoo logo name 2021-06-13 14:28:09 +02:00
Linus Dierheimer 889c8570f2 Merge branch 'master' of github.com:LinusDierheimer/fastfetch 2021-06-13 14:24:12 +02:00
Linus Dierheimer 3ce12dfc47 rewrote logo code 2021-06-13 14:23:35 +02:00
Linus Dierheimer 020fdccaaf Merge pull request #63 from wizard-28/grammer
Improve grammer of the configuration file
2021-06-13 14:15:56 +02:00
Sourajyoti Basak f82a4a6d7d Improve grammer of the configuration file 2021-06-13 17:44:34 +05:30
Linus Dierheimer 32f520bf3b Merge pull request #62 from wizard-28/master
Optimize the images using ImgBot
2021-06-12 18:22:21 +02:00
Sourajyoti Basak fc3cfff1d4 Optimize images
[ImgBot] Optimize images
2021-06-12 20:55:30 +05:30
ImgBotApp 36df822ce6 [ImgBot] Optimize images
*Total -- 119.87kb -> 102.20kb (14.74%)

/screenshots/ffmanjaro.png -- 47.30kb -> 38.92kb (17.71%)
/screenshots/example.png -- 72.56kb -> 63.27kb (12.8%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2021-06-12 15:07:10 +00:00
Linus Dierheimer 4d565cb7ee Fix snap package count 2021-06-10 22:04:25 +02:00
Linus Dierheimer 580ad45459 Fedora support 2021-06-08 20:01:29 +02:00
Linus Dierheimer 9535aa885c battery don't show full status 2021-05-30 21:37:27 +02:00
Linus Dierheimer 6a65803929 prettier battery output 2021-05-30 21:35:04 +02:00
Linus Dierheimer 602c3767e5 Rewrote WM / DE detection 2021-05-30 20:28:15 +02:00
Linus Dierheimer 0b93feaa94 removed debug puts 2021-05-28 14:14:57 +02:00
Linus Dierheimer 49e7612795 fix logo display 2021-05-28 14:10:53 +02:00
Linus Dierheimer 0e8b1fff8e Merge pull request #57 from alborrajo/master
Custom logos read from files
2021-05-28 13:48:03 +02:00
alborrajo e4516dc548 Clean up buffer after loading logo from file 2021-05-28 13:46:33 +02:00
alborrajo 936c478a9a Moved --logo-file bash completions to path options 2021-05-28 13:46:22 +02:00
alborrajo de72ea6ee6 Separate --logo-file option 2021-05-27 17:13:26 +02:00
alborrajo 53389850c2 Faster removal of \n when loading a custom logo 2021-05-27 16:40:51 +02:00
alborrajo a10aa36b72 Revert "Custom logos explanation in readme"
This reverts commit ec82b80f5a.
2021-05-27 15:57:17 +02:00
alborrajo f20ec0ef9f Color support on custom logos 2021-05-27 15:56:11 +02:00
alborrajo b9c6830a14 Merge branch 'master' of https://github.com/LinusDierheimer/fastfetch 2021-05-27 15:48:15 +02:00
Linus Dierheimer 94e4443464 fix --color option 2021-05-27 14:56:31 +02:00
alborrajo ec82b80f5a Custom logos explanation in readme 2021-05-26 19:20:11 +02:00
alborrajo e630167585 Read custom logos from text files
If the --logo option is specified with a path to a file, use the
contents of the file as the logo
2021-05-26 19:01:31 +02:00
Linus Dierheimer 137b3f7010 mutter wm theme fix 2021-05-24 10:46:55 +02:00
Linus Dierheimer 571913ed44 better mutter theme 2021-05-23 21:50:01 +02:00
Linus Dierheimer 76f9da4b78 added missing const 2021-05-23 21:03:11 +02:00
Linus Dierheimer 72fbcf94ff better Mutter detection 2021-05-23 20:35:24 +02:00
Linus Dierheimer 9f7f57dfd8 Better handling of Mutter in not GNOME systems 2021-05-23 19:56:49 +02:00
Linus Dierheimer bd3c236480 a bit better parsing of fonts 2021-05-23 19:40:34 +02:00
Linus Dierheimer 14932466f7 refactored usage of GSettings 2021-05-20 20:06:08 +02:00
Linus Dierheimer dbfa9dcc1f Merge pull request #54 from DarNCelsius/patch-1
Update README.md
2021-05-20 16:06:46 +02:00
DarN cd56317186 Update README.md 2021-05-19 20:08:29 +02:00
DarN 6b40174656 Update README.md
Added Gnome Terminal to Terminal Fonts section
2021-05-19 19:43:16 +02:00
Linus Dierheimer f1c3b5275f Merge pull request #51 from DarNCelsius/master
Refactored terminal font functions
2021-05-18 15:38:34 +02:00
DarN 5dc5ac6d29 Merge branch 'master' of https://github.com/DarNCelsius/fastfetch 2021-05-17 23:04:48 +02:00
DarN 5b69bd77a6 Terminal font refactor 2021-05-17 23:02:27 +02:00
Linus Dierheimer f19a1f40be Merge pull request #50 from DarNCelsius/master
Added terminal font support for Gnome Terminal
2021-05-17 21:28:17 +02:00
DarN 15ed8504bf Syntax change 2021-05-17 14:32:51 +02:00
DarN 4191bd8865 Merge branch 'master' of https://github.com/DarNCelsius/fastfetch 2021-05-17 14:24:15 +02:00
DarN 00c426c98a Added terminal font support for Gnome Terminal 2021-05-17 14:21:55 +02:00
Linus Dierheimer 2bb4407030 Merge pull request #49 from DarNCelsius/master
Enhanced LXQt DE Support
2021-05-17 11:16:11 +02:00
DarN 67edfd7f59 Added more file checks 2021-05-17 11:10:56 +02:00
DarN a1985bd7e8 Update README.md
Added LXQt version
2021-05-17 07:52:16 +02:00
DarN bfc9384ce3 Added Manjaro screenshot 2021-05-17 07:13:09 +02:00
DarN 82674a7d14 Rewrote with fast and slow modes 2021-05-17 06:34:48 +02:00
DarN 0531afadb7 Merge branch 'LinusDierheimer:master' into master 2021-05-17 06:15:10 +02:00
Linus Dierheimer 142d9c30e0 faster ffGetPropValue 2021-05-16 21:02:06 +02:00
Linus Dierheimer c8a9f06b52 added multiline and xml support to ffGetPropValue 2021-05-16 18:41:00 +02:00
Linus Dierheimer 5f71ef71da small syntactic changes 2021-05-16 15:10:15 +02:00
DarN dbde798a56 Added LXQt DE Version info 2021-05-16 14:00:04 +02:00
Linus Dierheimer 8af1cde10b Merge pull request #48 from DarNCelsius/master
Changed ffStrbufRemoveStringsA() iterator logic
2021-05-16 11:24:03 +02:00
DarN 852d6dcdcb Changed ffStrbufRemoveStringsA iterator logic 2021-05-16 07:36:14 +02:00
Linus Dierheimer c49fed470a Merge pull request #45 from DarNCelsius/patch-1
Change order of WMs in README.md
2021-05-15 18:20:48 +02:00
DarN f7e0e70b2f Tweaks
It's an OCD thing. 😀
2021-05-15 18:18:58 +02:00
Linus Dierheimer 44339971bd pass manjaro pacman branch to format string 2021-05-15 18:17:34 +02:00
Linus Dierheimer d12edd02bf Merge pull request #44 from DarNCelsius/master
Added branch detection for Manjaro
2021-05-15 18:12:55 +02:00
DarN 0dbcce84f8 Implemented changes 2021-05-15 18:12:10 +02:00
DarN 0e2deb3534 Rewrote with suggestions 2021-05-15 17:21:02 +02:00
Linus Dierheimer bbb46e7c66 better ffGetPropValue 2021-05-15 14:58:43 +02:00
DarN 25d23b020e Merge branch 'LinusDierheimer:master' into master 2021-05-15 14:52:28 +02:00
Linus Dierheimer 2ee2c68db5 ffGetPropValue trim result 2021-05-15 14:42:14 +02:00
DarN e400ee4490 Tweak 2021-05-15 13:44:16 +02:00
DarN bbd41e6c7a Merge branch 'LinusDierheimer:master' into master 2021-05-15 13:22:34 +02:00
DarN f24f6756b1 Added branch detection for Manjaro 2021-05-15 13:21:59 +02:00
Linus Dierheimer cedde7eced Merge pull request #43 from DarNCelsius/master
Renamed all instances of 'seperator'
2021-05-15 12:44:31 +02:00
DarN ca08e07c37 Renamed all instances of 'seperator' 2021-05-15 12:36:25 +02:00
Linus Dierheimer a72e3fed29 Merge pull request #42 from DarNCelsius/Grammar-fastfetch.c
Typos and grammar
2021-05-15 11:38:19 +02:00
DarN d815f624db Typos and grammar
I only did comments and help text - You might wanna change the "--seperate" option.
```
sep·a·rate
    a. To set, force, or keep apart: The referee separated the two boxers.
    b. To put space between; space apart or scatter: small farms that were separated one from another by miles of open land.
    c. To form a border or barrier between (two areas or groups): A hedge separates the two yards.
    d. To place in different groups; sort: separate mail by postal zones.
```
2021-05-15 08:39:20 +02:00
Linus Dierheimer 635f31eae1 better Host output 2021-05-14 16:03:19 +02:00
Linus Dierheimer 8128db974b updated README.md 2021-05-14 12:58:27 +02:00
Linus Dierheimer a841489280 updated README.md 2021-05-14 12:53:53 +02:00
Linus Dierheimer 0e94658683 updated README.md 2021-05-14 12:47:12 +02:00
Linus Dierheimer 225bcbe89a Mate support 2021-05-14 12:43:54 +02:00
Linus Dierheimer ae01d28094 btw preset 2021-05-14 10:44:41 +02:00
Linus Dierheimer d14a398f17 updated readme 2021-05-13 21:27:24 +02:00
Linus Dierheimer 1e82780de7 updated screenshot 2021-05-13 21:24:03 +02:00
Linus Dierheimer 35681ec09f flashfetch logo detection at compile time 2021-05-13 17:39:08 +02:00
Linus Dierheimer 0940064759 Merge pull request #40 from DarNCelsius/patch-3
Fixed dconf library load snafu
2021-05-13 14:09:05 +02:00
DarN 959750de3d Fixed dconf library load snafu
Typo :)
2021-05-13 13:53:29 +02:00
Linus Dierheimer 9e597aa253 fix ffGetPropValue 2021-05-13 12:48:00 +02:00
Linus Dierheimer 4d7a06ac97 ffGetPropValue 2021-05-13 12:27:44 +02:00
Linus Dierheimer f8868ae3c4 ffPrintError don't print regexes 2021-05-12 20:17:16 +02:00
Linus Dierheimer 7afc27e52f small syntactic changes 2021-05-12 20:13:56 +02:00
Linus Dierheimer 1ece13c36f Merge pull request #36 from DarNCelsius/master
Added system font recognition for xfce-terminal
2021-05-12 19:54:56 +02:00
DarN c549c7c868 Rewrote function with XFConf 2021-05-11 22:28:10 +02:00
DarN cac0c27807 Merge branch 'LinusDierheimer:master' into master 2021-05-11 20:18:05 +02:00
Linus Dierheimer 039b69f4a7 better ffSettings* functions 2021-05-11 20:06:17 +02:00
Linus Dierheimer 97ab892051 renamed printWMThemeFromConfig to keep consistency 2021-05-09 22:09:01 +02:00
Linus Dierheimer 6cfe826cd7 replaced wrong format string 2021-05-09 22:04:18 +02:00
Linus Dierheimer e89b326d57 basic XFCE support 2021-05-09 21:41:17 +02:00
DarN ef3f4d9fa8 Tweaks
Hopefully an improvement
2021-05-09 20:39:00 +02:00
DarN 89187e9758 Removed auto include 2021-05-09 14:07:20 +02:00
DarN cf4b3c54cf Added check for manual edits 2021-05-09 14:05:57 +02:00
DarN 719a5c999d Added system font recognition for xfce-terminal 2021-05-09 13:40:17 +02:00
Linus Dierheimer 7432fc7a19 fixed WM::getFromProcDir 2021-05-09 12:56:07 +02:00
Linus Dierheimer ed2b72e0cf fixed unnecessary format string evaluation in ffPrintError 2021-05-09 12:39:44 +02:00
Linus Dierheimer b5454c28bf unified some terminal font methods 2021-05-09 12:30:10 +02:00
Linus Dierheimer fc314e6ded Merge pull request #35 from DarNCelsius/master
Added Terminal Font for lxterminal
2021-05-09 12:24:34 +02:00
DarN 479188ec3e Added lxterminal 2021-05-09 09:04:31 +02:00
DarN 70c1b477d0 Added Terminal Font for lxterminal 2021-05-09 09:02:56 +02:00
DarN 0e236c7d6a Cleanup/Note on future changes 2021-05-09 08:03:09 +02:00
Linus Dierheimer cdf82e91b2 Merge pull request #33 from DarNCelsius/patch-2
Update README.md
2021-05-08 22:04:05 +02:00
DarN 476988f695 Update README.md
Tilix, grammar
2021-05-08 22:02:50 +02:00
Linus Dierheimer 123d19bb69 Merge pull request #32 from DarNCelsius/patch-1
Added Terminal Font for Tilix
2021-05-08 21:31:37 +02:00
DarN 099ddeea01 Tweaks
Are we there yet? :D
2021-05-08 21:26:01 +02:00
DarN eac718085e Implemented suggestions
Much better.
2021-05-08 21:17:04 +02:00
Linus Dierheimer 30953a31dc small changes to memory managment 2021-05-08 21:13:58 +02:00
DarN 4f83dc8396 Added Terminal Font for Tilix
This adds Terminal Font recognition for Tilix's default profile. I can't find a way to detect which profile is the active one.
2021-05-08 20:31:18 +02:00
Linus Dierheimer dfeb5c49e1 updated FFvariant 2021-05-08 18:58:40 +02:00
Linus Dierheimer b054fec8d8 updated README 2021-05-08 18:35:51 +02:00
Linus Dierheimer c8cd51da84 variant for dconf 2021-05-08 17:56:56 +02:00
Linus Dierheimer a6cd29057b Merge pull request #31 from DarNCelsius/patch-4
Grammar
2021-05-08 17:21:13 +02:00
Linus Dierheimer 62f1c5d059 dont show gpu index on single gpu systems 2021-05-08 17:18:59 +02:00
DarN e249c1590a Grammar
I couldn't help myself. 😁
2021-05-08 17:13:26 +02:00
Linus Dierheimer e4a61c3572 updated initCacheDir 2021-05-08 16:56:37 +02:00
Linus Dierheimer c749763f05 updated ffAppendFDContent 2021-05-08 16:24:57 +02:00
Linus Dierheimer bd316496a2 better handling of cache directory 2021-05-08 12:14:55 +02:00
Linus Dierheimer 79810542af Merge pull request #29 from DarNCelsius/patch-2
Added .cache folder
2021-05-08 11:48:33 +02:00
DarN f09aae6541 Added .cache folder 2021-05-08 11:37:50 +02:00
Linus Dierheimer 7609a24778 Cinnamon support 2021-05-08 11:20:17 +02:00
Linus Dierheimer eea74b085b prettier GPU output 2021-05-07 17:10:22 +02:00
Linus Dierheimer 4e49416394 fixed DE output when SESSION_DESKTOP == WM 2021-05-07 16:16:23 +02:00
Linus Dierheimer a389b89ff0 supprt for custom / multiple config dirs 2021-05-07 14:55:43 +02:00
Linus Dierheimer ebc42b8f8b default KWin theme 2021-05-07 11:02:09 +02:00
Linus Dierheimer ec941bcb33 improoved GTK detection 2021-05-07 10:34:30 +02:00
Linus Dierheimer 91b7967677 fixed battery status 2021-05-05 21:29:09 +02:00
Linus Dierheimer cb61fde75d fixed X- truncating on DE output number 2 2021-05-05 21:26:42 +02:00
Linus Dierheimer 20322c4fe4 fixed X- truncating on DE output 2021-05-05 21:18:29 +02:00
Linus Dierheimer a7784f5a88 better os output 2021-05-05 21:12:42 +02:00
Linus Dierheimer 89aa4470aa support for gsettings bool value 2021-05-05 20:20:41 +02:00
Linus Dierheimer 14d3e3b1b3 dont show unknown battery status 2021-05-05 19:52:50 +02:00
Linus Dierheimer bc870197d7 remove X- from DE names 2021-05-05 19:49:40 +02:00
Linus Dierheimer 9c26f9d988 fix help gpu-format 2021-05-05 19:31:58 +02:00
Linus Dierheimer 7da0c76703 fixed ffSettingsGetDConf 2021-05-04 21:25:50 +02:00
Linus Dierheimer 7ec32bf5d3 ffSettingsGet* 2021-05-04 19:48:23 +02:00
Linus Dierheimer bd2e1da3b4 small fixes 2021-05-02 21:45:47 +02:00
Linus Dierheimer 88d2530460 better transforming from gsettings to dconf 2021-05-02 21:30:05 +02:00
Linus Dierheimer 286095a09a transform GSettings path to dconf key style 2021-05-02 21:12:03 +02:00
Linus Dierheimer f47a44f47a added ffGSettingsGetValuePath 2021-05-02 21:06:01 +02:00
Linus Dierheimer 35504b33b1 ffGSettingsGetValue 2021-05-02 18:52:42 +02:00
Linus Dierheimer 56c0e9d068 Merge pull request #26 from DarNCelsius/patch-1
Removed leftover puts()
2021-05-02 08:36:28 +02:00
DarN 46306d913f Removed leftover puts() 2021-05-02 05:26:46 +02:00
Linus Dierheimer 6917164271 updated ffDConfGetValue 2021-05-01 21:55:15 +02:00
Linus Dierheimer 39f0f9c483 updated README 2021-05-01 21:31:03 +02:00
Linus Dierheimer fb17273ec4 close stderr of child process 2021-05-01 21:27:46 +02:00
Linus Dierheimer 85c7f4c772 basic gnome support 2021-05-01 21:22:07 +02:00
Linus Dierheimer 6e8e2e6c47 fixed dconf bug #2 2021-05-01 17:25:22 +02:00
Linus Dierheimer 97ae9e9d28 fixed dconf bug 2021-05-01 17:19:17 +02:00
Linus Dierheimer 94caa86998 TTY improvements 2021-05-01 16:54:59 +02:00
Linus Dierheimer e66e78fcc5 removed wrong paths used for testing 2021-05-01 16:06:12 +02:00
Linus Dierheimer 6eddc6105f ffDconfGetValue 2021-05-01 16:01:59 +02:00
Linus Dierheimer 671842d316 merge branch 2021-05-01 13:04:15 +02:00
Linus Dierheimer f3c8ecacbb greatly improved WM / DE detection 2021-05-01 13:03:30 +02:00
Linus Dierheimer 2618465121 Merge pull request #24 from DarNCelsius/patch-1
Update README.md
2021-04-29 15:47:19 +02:00
DarN 7f4dba8856 Update README.md
Typos, grammar and double Muffin
2021-04-29 15:34:55 +02:00
Linus Dierheimer e3f3699b26 improved WM detection 2021-04-28 21:48:23 +02:00
Linus Dierheimer c3f7ed5247 merged changes 2021-04-28 19:54:03 +02:00
Linus Dierheimer 01ada03c5c renamed calculate to detect 2021-04-28 19:53:30 +02:00
Linus Dierheimer 5c93d70341 Merge pull request #23 from DarNCelsius/patch-3
Updated help documentation
2021-04-28 19:52:01 +02:00
Linus Dierheimer bbeddbe403 Merge pull request #22 from DarNCelsius/patch-2
Added Package Manager support for Void Linux
2021-04-28 19:51:49 +02:00
DarN 644843a70d Implemented corrections 2021-04-28 19:50:04 +02:00
DarN d403c035d0 Updated help documentation
Quick grammar corrections as a bonus ;)
2021-04-28 19:45:43 +02:00
DarN dd31e05fde Update packages.c 2021-04-28 16:05:06 +02:00
DarN 99849ccd77 Debloat
...
2021-04-28 07:10:55 +02:00
DarN 4674d6c2fc Removed useless enum 2021-04-28 06:59:44 +02:00
DarN f938847459 Added missing else
No need to compare twice if the first one checks out...
2021-04-28 06:46:20 +02:00
DarN f4d2b35260 Added Package Manager support for Void Linux
This adds support for xbps.
2021-04-27 21:52:55 +02:00
Linus Dierheimer b83499d1ec updated readme 2021-04-26 21:56:21 +02:00
Linus Dierheimer 2449681f30 Merge pull request #21 from DarNCelsius/patch-1
Added additional WM Theme support
2021-04-26 21:50:13 +02:00
DarN dd709461a5 Small correction
Something is adding this include automatically...
2021-04-26 21:49:12 +02:00
DarN dbc576862e Made corrections
Something like this?
2021-04-26 21:46:57 +02:00
DarN a4d4b66679 Implemented suggested changes 2021-04-26 20:47:32 +02:00
DarN 6bcf3bab7c Cleaned up whitespace 2021-04-26 17:39:05 +02:00
DarN 41dc49f170 Update wmtheme.c 2021-04-26 17:27:12 +02:00
Linus Dierheimer 2a29d3ed17 better handling of WM / DE 2021-04-25 21:32:35 +02:00
DarN 6c612cbd9a Added additional WM Theme support
Supports LXQt, LXDE and Openbox
2021-04-25 21:18:56 +02:00
Linus Dierheimer e9cf1c0252 fixed a bug in ffStrbufTrimRight 2021-04-25 19:12:05 +02:00
Linus Dierheimer 7da4e5b69a ffStrbufTrimLeft now sets a null byte at the end 2021-04-25 19:03:59 +02:00
Linus Dierheimer ffd5b45b2c added support status to README.md 2021-04-25 16:16:40 +02:00
Linus Dierheimer 843a9811d0 paleofetch preset 2021-04-25 15:22:35 +02:00
Linus Dierheimer 6b066911dd garuda logo support 2021-04-25 15:07:31 +02:00
Linus Dierheimer f4a691ebd6 neofetch preset 2021-04-25 14:21:28 +02:00
Linus Dierheimer ec76f1c2d9 updated readme 2021-04-25 12:31:39 +02:00
Linus Dierheimer dffbd4f0f0 fixed a compiler warning 2021-04-25 11:56:01 +02:00
Linus Dierheimer f7b6fb2d4f presets 2021-04-25 11:48:25 +02:00
Linus Dierheimer 1b1d28f0ab color in format strings 2021-04-25 09:13:18 +02:00
Linus Dierheimer d469120e9b format string more like template language 2021-04-24 21:42:48 +02:00
Linus Dierheimer 36a4d095ed better handling of custom disk folders string 2021-04-24 16:29:05 +02:00
Linus Dierheimer ad122e9569 better handling of custom battery dir 2021-04-24 14:37:40 +02:00
Linus Dierheimer fc1c17932e fixed battery key index on multi battery systems 2021-04-24 14:25:27 +02:00
Linus Dierheimer 2ba1fb0868 typo in battery 2021-04-24 13:17:30 +02:00
Linus Dierheimer 49e112eeae revert stupid revert 2021-04-24 13:12:40 +02:00
Linus Dierheimer c5c3cecb93 support for more than 5 batteries 2021-04-24 13:05:43 +02:00
Linus Dierheimer 025dbecc4f Merge pull request #17 from DarNCelsius/patch-2
Added support for additional window managers
2021-04-24 11:58:04 +02:00
DarN 85c49f6873 Fixed cinnamon wm name... 2021-04-24 10:39:53 +02:00
DarN adce9fc53d Added support for additional window managers
Added support for Openbox, Cinnamon, XFCE and Wayfire window managers.
2021-04-24 10:25:39 +02:00
Linus Dierheimer c697f8ee80 print 144 instead of 145 refresh rate as this rate is more common 2021-04-23 21:13:50 +02:00
Linus Dierheimer eddc01290a Small improvements to host output 2021-04-23 20:59:13 +02:00
Linus Dierheimer 283e4f56e9 added missing mutex unlocks 2021-04-23 20:44:52 +02:00
Linus Dierheimer e28126f40e better result handling of calculation functions 2021-04-22 21:41:42 +02:00
Linus Dierheimer c12484ec6b Merge pull request #13 from DarNCelsius/patch-1
Added support for Void Linux
2021-04-21 19:50:34 +02:00
DarN b1df0ef98a Added support for Void Linux 2021-04-21 19:45:57 +02:00
Linus Dierheimer a64dc74923 updated screenshot 2021-04-18 22:51:55 +02:00
Linus Dierheimer 3e9ce54f63 --nocache option added 2021-04-18 19:23:54 +02:00
Linus Dierheimer 1d47eb0c60 shell version support 2021-04-18 15:19:21 +02:00
Linus Dierheimer 3e9678c899 small x11 improovement 2021-04-17 15:07:53 +02:00
Linus Dierheimer 4e54117238 better cpu name prettifier 2021-04-17 14:37:32 +02:00
Linus Dierheimer 44ddfc2a03 updated README.md 2021-04-17 12:21:59 +02:00
Linus Dierheimer eae92b6306 Merge pull request #12 from DarNCelsius/master
Thanks for the PR.
2021-04-17 12:03:23 +02:00
DarNCelsius b7c0c18497 Merge pull request #1 from DarNCelsius/DarNCelsius-patch-1
Update logo.c
2021-04-17 11:29:19 +02:00
DarNCelsius 61188b68a4 Update logo.c
Added Manjaro to known logos
2021-04-17 11:25:38 +02:00
Linus Dierheimer 51c38a2b01 terminalfont now gives an error on unknown terminals instead of printing TTY values 2021-04-16 20:44:46 +02:00
Linus Dierheimer 7b65316483 global results are now stored in state 2021-04-16 20:22:38 +02:00
Linus Dierheimer 86abc05cd4 removed obsolete recache condition 2021-04-16 17:51:17 +02:00
Linus Dierheimer 1d878215ae unified FFformatarg printing 2021-04-16 17:46:50 +02:00
Linus Dierheimer a145700500 wayland support 2021-04-16 16:49:33 +02:00
Linus Dierheimer f27f08a6e2 updated screenshot 2021-04-15 19:22:19 +02:00
Linus Dierheimer 9bc1f2a116 much more efficient caching 2021-04-15 18:59:26 +02:00
Linus Dierheimer ed598eaa35 updated readme 2021-04-09 19:48:16 +02:00
Linus Dierheimer 0ed54eddc4 plasma color theme detection 2021-04-09 19:21:56 +02:00
Linus Dierheimer 2b55a14c16 GTK dconf backend doesn't append already set values anymore 2021-04-09 16:11:53 +02:00
Linus Dierheimer 53c781aa21 project structure refactoring 2021-04-09 14:07:05 +02:00
Linus Dierheimer 0649b6e755 format once again works for theme/icons/font 2021-04-07 21:07:32 +02:00
Linus Dierheimer 9321241830 always unlock mutex on errors 2021-04-07 18:46:51 +02:00
Linus Dierheimer c698080581 basic multithreading 2021-04-07 17:36:03 +02:00
Linus Dierheimer ed7e186f4b faster plasma detection 2021-04-07 12:55:11 +02:00
Linus Dierheimer 5f23f2b027 small refactoring 2021-04-06 11:36:05 +02:00
Linus Dierheimer c543bcc29f optional gtk detection via dconf 2021-04-05 23:42:07 +02:00
Linus Dierheimer de312adb52 better gtk detection 2021-04-05 19:25:34 +02:00
Linus Dierheimer af430bd405 fixed a bug in battery where manufacturer was printed twice instead of model 2021-04-03 23:25:01 +02:00
Linus Dierheimer 1086c059b6 updated screenshot 2021-04-03 23:12:59 +02:00
Linus Dierheimer f25bca3dab wm theme detection for kde plasma 2021-04-03 23:10:14 +02:00
Linus Dierheimer e01d03f98d dont use format string if an error occures 2021-04-03 21:51:50 +02:00
Linus Dierheimer 67465d266e more efficient memory usage 2021-04-03 12:14:25 +02:00
Linus Dierheimer 08066a76f0 all keys can now be set! 2021-04-03 11:39:59 +02:00
Linus Dierheimer a8821cf6f0 some terminal improvements 2021-04-02 16:21:52 +02:00
Linus Dierheimer 9c26a76c9d WM is once again shown in a plasma session 2021-03-28 20:36:49 +02:00
Linus Dierheimer 307fc61184 better structure looping 2021-03-28 20:09:29 +02:00
Linus Dierheimer c44bd6dbc1 better disk output 2021-03-28 15:38:52 +02:00
Linus Dierheimer 184eafce20 better cpu output 2021-03-28 13:02:40 +02:00
Linus Dierheimer efc0322ed1 print default structure / modules 2021-03-27 19:26:58 +01:00
Linus Dierheimer b3c3614b6c fixed a bug in os module with version codename 2021-03-27 18:39:13 +01:00
Linus Dierheimer 693f8a33db fixed a bug in os module where it would show apostophes around values 2021-03-27 18:38:00 +01:00
Linus Dierheimer 44549e32d9 removed remaining strcat 2021-03-27 18:35:30 +01:00
Linus Dierheimer a1e90ba35c editorconfig 2021-03-27 18:14:19 +01:00
Linus Dierheimer 46ed1b34cb much faster reading of large files 2021-03-27 17:55:16 +01:00
Linus Dierheimer 23db257af9 much more values in os-format 2021-03-27 17:48:32 +01:00
Linus Dierheimer beb2e9608c dont print line if format evaluates to an empty string 2021-03-27 15:39:56 +01:00
Linus Dierheimer 055804a055 removed ffTrimTrailingWhitespace 2021-03-27 14:22:08 +01:00
Linus Dierheimer f61ffdb149 removed ffStrbufIsEmpty 2021-03-23 19:48:52 +01:00
Linus Dierheimer a0af3b0eb6 ffStrbufPutTo 2021-03-22 20:02:32 +01:00
Linus Dierheimer 2021709d72 if host version is None, dont show it 2021-03-22 19:52:59 +01:00
Linus Dierheimer 4d736fd5d0 updated .gitignore 2021-03-22 19:16:45 +01:00
Linus Dierheimer 02c450c218 rewinding file descriptor before trying reading again 2021-03-22 19:15:51 +01:00
Linus Dierheimer 071b2c6727 print logo in ffPrintAndSaveCachedValue 2021-03-21 20:46:20 +01:00
Linus Dierheimer 2004544528 using strbuf for loading/saving cached values 2021-03-21 20:42:07 +01:00
Linus Dierheimer c783bb9d97 renamed spacer to spacing 2021-03-21 17:02:31 +01:00
Linus Dierheimer 101d19a015 ffGetFileContent now uses FFstrbuf for preventing buffer overflows 2021-03-21 16:52:17 +01:00
Linus Dierheimer 0d3500c66f command help 2021-03-21 11:18:06 +01:00
Linus Dierheimer a848798e97 Merge pull request #7 from saloniamatteo/master
Locale: implement /etc/locale.conf fallbacks
2021-03-21 09:58:49 +01:00
saloniamatteo 9d5481e83a Sane indentation: use tabs instead of spaces 2021-03-20 11:24:35 +01:00
saloniamatteo 05fe281141 Fully implement LANG fallbacks 2021-03-20 11:20:37 +01:00
saloniamatteo 3d27ecaba8 Free pointer to file 2021-03-20 10:47:49 +01:00
saloniamatteo e70f06087c Merge branch 'master' of github.com:saloniamatteo/fastfetch 2021-03-20 10:47:18 +01:00
saloniamatteo e2986b198f Free pointer to file 2021-03-20 10:46:56 +01:00
Salonia Matteo e479b62c73 Merge pull request #2 from LinusDierheimer/master
Sync from upstream pt. 2
2021-03-20 09:45:58 +00:00
saloniamatteo e531278e62 Experimental: use fallback for LANG 2021-03-20 10:39:05 +01:00
Salonia Matteo a8ca2ce825 Sync from upstream 2021-03-20 07:09:02 +00:00
Linus Dierheimer 92b1247683 print remaining logo by default 2021-03-19 21:23:15 +01:00
Linus Dierheimer dd19fcfded Merge pull request #4 from saloniamatteo/master
Thanks for this contribution. Note that i dont test on Ubuntu / Debian (yet), so probably a lot of stuff wont work on those platforms.
2021-03-19 21:03:23 +01:00
Linus Dierheimer db35000e39 Merge branch 'master' into master 2021-03-19 21:02:23 +01:00
Linus Dierheimer 1ceb5c91ac format options for every output! 2021-03-19 20:57:07 +01:00
Matteo cddfc083c3 Merge branch 'master' into master 2021-03-19 18:27:03 +00:00
saloniamatteo f358e07b84 Update logo list 2021-03-19 19:21:22 +01:00
saloniamatteo 74b315a1d1 Update logo list 2021-03-19 19:21:05 +01:00
saloniamatteo 9d28df2922 Sync with upstream 2021-03-19 19:19:46 +01:00
saloniamatteo 016acb8e9e src/logo.c: Fix potential security flaw when using printf
Warning: Format string is not a literal string, when using printf
without "%s" (eg. printf(something), instead of printf("%s", something))
2021-03-19 19:12:52 +01:00
saloniamatteo e53f84bb27 Add debian logo 2021-03-19 19:09:14 +01:00
saloniamatteo fd3215ed3b Add debian logo 2021-03-19 19:08:46 +01:00
saloniamatteo be9272c2e9 Add ubuntu logo 2021-03-19 18:45:30 +01:00
saloniamatteo eb7ce05193 Fix logo spacing 2021-03-19 17:56:30 +01:00
Linus Dierheimer 5c6bbbf677 fixed artix logo width 2021-03-19 17:53:48 +01:00
Linus Dierheimer cf9af7023f fixed bug in artix logo 2021-03-19 17:51:52 +01:00
Linus Dierheimer 370de39169 Merge pull request #3 from saloniamatteo/master
Add support for Artix
2021-03-19 17:48:34 +01:00
saloniamatteo 05f11c6c69 Add support for Artix, fix code block in README 2021-03-19 08:43:29 +01:00
saloniamatteo a0169d83e5 Add support for Artix 2021-03-19 08:39:27 +01:00
Linus Dierheimer 37dd06590a --host-format 2021-03-12 12:16:41 +01:00
Linus Dierheimer 8e9cb079b0 new screenshot 2021-03-12 10:31:39 +01:00
Linus Dierheimer a6c153da95 --os-format 2021-03-12 10:17:49 +01:00
Linus Dierheimer b9c7324aa5 resolution options 2021-03-11 22:15:48 +01:00
Linus Dierheimer c988777c79 small changes to package options 2021-03-11 19:54:34 +01:00
Linus Dierheimer 0169507489 packages options 2021-03-11 19:40:46 +01:00
Linus Dierheimer 33be85c4bc terminal font 2021-03-11 17:21:18 +01:00
Linus Dierheimer abd797a0bf added .gitattributes 2021-03-07 20:56:01 +01:00
Linus Dierheimer aa5b5f3caf kernel options 2021-03-07 20:35:17 +01:00
Linus Dierheimer 6cc99423c9 performance tests 2021-03-07 20:05:00 +01:00
Linus Dierheimer 43022c0129 updated README.md 2021-03-07 13:25:32 +01:00
Linus Dierheimer 6e11609432 some content in README.md 2021-03-07 13:12:45 +01:00
Linus Dierheimer 2240264d02 --host-version 2021-03-07 11:58:24 +01:00
Linus Dierheimer dbeaa342ba bash completion improvements 2021-03-07 11:11:21 +01:00
Linus Dierheimer 16af140f7a basic bash completion 2021-03-06 22:40:05 +01:00
Linus Dierheimer 923faa63e5 --os-architecture option 2021-03-06 11:28:38 +01:00
Linus Dierheimer bc13b51b5a support for --shell-path 2021-03-05 23:26:05 +01:00
Linus Dierheimer 9122daa63a seperator support 2021-03-05 23:00:28 +01:00
Linus Dierheimer 61b369ea19 version information in config file 2021-03-05 21:49:13 +01:00
Linus Dierheimer 22cfe4df1f basic Window Manager detection 2021-03-05 21:38:35 +01:00
Linus Dierheimer f65105d181 battery-format 2021-03-04 20:49:12 +01:00
Linus Dierheimer f67a5f3879 prettier default config 2021-03-03 21:42:40 +01:00
Linus Dierheimer c1fb9525b8 battery options 2021-03-03 21:03:12 +01:00
Linus Dierheimer b95dd4ce17 fixed a missing newline in help output 2021-03-03 20:05:21 +01:00
Linus Dierheimer db6d2eb3a3 structure and values can be set in fastfetch via command line and file! 2021-03-03 19:59:39 +01:00
Linus Dierheimer 4dffbb0bb7 battery rework 2021-03-01 19:53:20 +01:00
Linus Dierheimer 7248daaa48 loading pci libs dynamically 2021-02-28 17:38:26 +01:00
Linus Dierheimer 0617b597f9 flashfetch loads default values too now 2021-02-28 17:10:12 +01:00
Linus Dierheimer e06aab6836 use strcasecmp in some cases 2021-02-27 21:10:27 +01:00
Linus Dierheimer d1cec7d1e5 trim trailing whitespaces from keys 2021-02-27 21:04:50 +01:00
Linus Dierheimer 56751e4581 you can now load default values from files 2021-02-27 20:50:13 +01:00
Linus Dierheimer d3db1066e2 reading structure from file 2021-02-27 20:31:54 +01:00
Linus Dierheimer 0c3a562ec6 minor refactoring 2021-02-27 19:22:28 +01:00
Linus Dierheimer 1cda1eb653 refactored internal state keeping 2021-02-27 18:30:05 +01:00
Linus Dierheimer b44ab16dd1 refactored project structure 2021-02-27 16:40:05 +01:00
Linus Dierheimer 558639086a error handling in resolution.c 2021-02-27 14:46:31 +01:00
Linus Dierheimer 48a436ee78 reworked resolution 2021-02-27 14:40:03 +01:00
Linus Dierheimer 16239be51c no color options 2021-02-25 18:38:00 +01:00
Linus Dierheimer 3d902c1c86 removed testing line from CMakeLists.txt 2021-02-22 20:54:05 +01:00
Linus Dierheimer 0ec63d64fa fixed a bug in caching 2021-02-22 20:53:12 +01:00
Linus Dierheimer fea8e371e4 --version implementation 2021-02-22 20:36:25 +01:00
Linus Dierheimer 7cbe1c2359 increased possible input size for color 2021-02-22 19:34:34 +01:00
Linus Dierheimer 4b4f92eb74 fixed some compiler warnings 2021-02-22 17:14:46 +01:00
Linus Dierheimer df3dcb7ede caching of some values 2021-02-22 16:52:51 +01:00
Linus Dierheimer f14e84606f fixed a bug where the program would coredump on uptime < 60s 2021-02-22 14:01:15 +01:00
Linus Dierheimer 85bcf00cf8 cleaned main up 2021-02-22 13:45:14 +01:00
Linus Dierheimer 11b5d6e138 uint16_t for seperator, for those madmans out ther 2021-02-20 20:12:57 +01:00
Linus Dierheimer e3616d8b72 the seperator can now be set 2021-02-20 20:00:06 +01:00
Linus Dierheimer 61bac93809 setting color works 2021-02-20 19:32:57 +01:00
Linus Dierheimer 5d32a782a2 check if showErrors in ffPrintError 2021-02-20 19:08:23 +01:00
Linus Dierheimer 626badd3c8 fixed a bug where color is not set 2021-02-19 18:07:46 +01:00
Linus Dierheimer 12ed7a9812 logo system reqork 2021-02-19 18:02:36 +01:00
Linus Dierheimer f533767569 removed obsolete ffRead functions 2021-02-19 16:38:54 +01:00
Linus Dierheimer a8f165e5c9 better error handling 2021-02-19 16:23:41 +01:00
Linus Dierheimer c5a9b9d428 fixed a bug that caused segfault with -O3 2021-02-19 10:07:00 +01:00
Linus Dierheimer 41120ef582 not ignoring the result of fscanf 2021-02-18 23:04:31 +01:00
Linus Dierheimer 4b2c4a8821 added LICENSE and README 2021-02-18 22:30:16 +01:00
Linus Dierheimer ebb14afb26 initial work 2021-02-18 22:25:36 +01:00
Linus Dierheimer da5ab1c187 Initial commit 2021-02-18 22:25:20 +01:00
177 changed files with 18914 additions and 69996 deletions
+17
View File
@@ -0,0 +1,17 @@
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
[*.{txt,fflogo}]
insert_final_newline = false
[*.yml]
tab_width = 2
+2
View File
@@ -0,0 +1,2 @@
*.h linguist-language=c
*.c linguist-language=c
+1
View File
@@ -0,0 +1 @@
custom: paypal.me/linusdierheimer
+43
View File
@@ -0,0 +1,43 @@
---
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 --recache --multithreading false --disable-linewrap false`.
-->
+14
View File
@@ -0,0 +1,14 @@
---
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
@@ -0,0 +1,18 @@
---
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.
```
+122
View File
@@ -0,0 +1,122 @@
name: manage pushes
on:
- push
- pull_request
jobs:
linux:
name: Linux
runs-on: ubuntu-latest
permissions:
security-events: write
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
- 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 . -j$(nproc) --target package
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: ./flashfetch
- name: run tests
run: ctest
- name: get fastfetch version
id: ffversion
run: echo "::set-output name=ffversion::$(./fastfetch --version-raw)"
- 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
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: install required packages
run: brew install vulkan-loader
- 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 . -j$(sysctl -n hw.logicalcpu) --target package
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: ./flashfetch
- name: run tests
run: ctest
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-macos
path: ./fastfetch-*.*
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
name: Release
runs-on: ubuntu-latest
needs:
- linux
- macos
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/*
+8 -3
View File
@@ -1,3 +1,8 @@
/.cache
/.vscode
/build*
**/build/
**/.vscode/
**/.cache/
**/.kdev4/
**/.DS_Store
cscope.*
tags
fastfetch.kdev4
+114
View File
@@ -0,0 +1,114 @@
# 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
+444
View File
@@ -0,0 +1,444 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 1.7.2
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
)
###################
# Target Platform #
###################
if(APPLE OR ANDROID)
set(LINUX FALSE CACHE BOOL "..." FORCE) # Linux true means we have full linux userland, not just the kernel
elseif(UNIX)
set(LINUX TRUE CACHE BOOL "..." FORCE)
else()
message(FATAL_ERROR "Unsupported platform")
endif()
#####################
# Configure options #
#####################
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX" 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" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX" 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
#############################
# Compile time dependencies #
#############################
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
include(CheckIncludeFile)
####################
# Compiler options #
####################
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
# Used for dlopen finding dylibs installed by homebrew, reversed for future usage
# `/opt/homebrew/lib` is not on dlopen search path by default
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
endif()
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
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()
#################
# 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()
#############
# Text data #
#############
function(fastfetch_load_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
string(REPLACE "\n" "\\n" TEMP "${TEMP}")
string(REPLACE "\"" "\\\"" TEMP "${TEMP}")
string(REPLACE "$\\" "" TEMP "${TEMP}")
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/util/FFstrbuf.c
src/util/FFlist.c
src/util/FFvaluestore.c
src/common/init.c
src/common/io.c
src/common/printing.c
src/common/caching.c
src/common/properties.c
src/common/font.c
src/common/processing.c
src/common/format.c
src/common/parsing.c
src/common/settings.c
src/common/library.c
src/common/networking.c
src/logo/logo.c
src/logo/builtin.c
src/logo/image/image.c
src/logo/image/im7.c
src/logo/image/im6.c
src/detection/qt.c
src/detection/gtk.c
src/detection/terminalShell.c
src/detection/vulkan.c
src/detection/media.c
src/detection/datetime.c
src/detection/temps.c
src/detection/title.c
src/detection/host/host.c
src/detection/os/os.c
src/detection/cpu/cpu.c
src/detection/gpu/gpu.c
src/detection/memory/memory.c
src/detection/displayserver/displayserver.c
src/modules/break.c
src/modules/custom.c
src/modules/title.c
src/modules/separator.c
src/modules/os.c
src/modules/host.c
src/modules/kernel.c
src/modules/uptime.c
src/modules/processes.c
src/modules/packages.c
src/modules/shell.c
src/modules/resolution.c
src/modules/de.c
src/modules/wm.c
src/modules/wmtheme.c
src/modules/theme.c
src/modules/icons.c
src/modules/font.c
src/modules/cursor.c
src/modules/terminal.c
src/modules/terminalfont.c
src/modules/cpu.c
src/modules/cpuUsage.c
src/modules/gpu.c
src/modules/memory.c
src/modules/disk.c
src/modules/battery.c
src/modules/locale.c
src/modules/vulkan.c
src/modules/localip.c
src/modules/publicip.c
src/modules/player.c
src/modules/song.c
src/modules/datetime.c
src/modules/date.c
src/modules/time.c
src/modules/colors.c
src/modules/opengl.c
src/modules/opencl.c
)
if(APPLE)
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_apple.c
src/detection/os/os_apple.c
src/detection/cpu/cpu_apple.c
src/detection/gpu/gpu_apple.c
src/detection/memory/memory_apple.c
src/detection/displayserver/displayserver_apple.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_android.c
src/detection/os/os_android.c
src/detection/cpu/cpu_linux.c
src/detection/gpu/gpu_android.c
src/detection/memory/memory_linux.c
src/detection/displayserver/displayserver_android.c
)
else()
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_linux.c
src/detection/os/os_linux.c
src/detection/cpu/cpu_linux.c
src/detection/gpu/gpu_linux.c
src/detection/memory/memory_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/displayserver/linux/wmde.c
)
endif()
add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
CHECK_INCLUDE_FILE("sys/sysinfo.h" HAVE_SYSINFO_H)
if(HAVE_SYSINFO_H)
# needs to be public, because changes fastfech.h ABI
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_SYSINFO_H)
endif()
function(ff_lib_enable VARNAME)
if(NOT ENABLE_${VARNAME})
return()
endif()
foreach(LIBNAME ${ARGN})
pkg_check_modules(${VARNAME} ${LIBNAME})
if(${VARNAME}_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
target_link_directories(libfastfetch PRIVATE ${${VARNAME}_LIBRARY_DIRS})
return()
endif()
endforeach()
message(WARNING "Package ${ARGV1} not found, building without support.")
endfunction()
ff_lib_enable(LIBPCI libpci)
ff_lib_enable(VULKAN vulkan)
ff_lib_enable(WAYLAND wayland-client)
ff_lib_enable(XCB_RANDR xcb-randr)
ff_lib_enable(XCB xcb)
ff_lib_enable(XRANDR xrandr)
ff_lib_enable(X11 x11)
ff_lib_enable(GIO gio-2.0)
ff_lib_enable(DCONF dconf)
ff_lib_enable(DBUS dbus-1)
ff_lib_enable(XFCONF libxfconf-0)
ff_lib_enable(SQLITE3 sqlite3)
ff_lib_enable(RPM rpm)
ff_lib_enable(IMAGEMAGICK7 MagickCore-7.Q16HDRI MagickCore-7.Q16 /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc)
ff_lib_enable(IMAGEMAGICK6 MagickCore-6.Q16HDRI MagickCore-6.Q16 /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc)
ff_lib_enable(ZLIB zlib)
ff_lib_enable(CHAFA chafa>=1.10)
ff_lib_enable(EGL egl)
ff_lib_enable(GLX glx)
ff_lib_enable(OSMESA osmesa)
ff_lib_enable(OPENCL OpenCL)
if(APPLE)
target_link_libraries(libfastfetch
PRIVATE "-framework CoreFoundation"
PRIVATE "-framework IOKit"
PRIVATE "-framework CoreGraphics"
PRIVATE "-framework OpenGL"
PRIVATE "-framework OpenCL"
)
endif()
target_include_directories(libfastfetch
PUBLIC ${PROJECT_BINARY_DIR}
PUBLIC ${PROJECT_SOURCE_DIR}/src
)
target_link_libraries(libfastfetch
PRIVATE ${CMAKE_DL_LIBS}
PRIVATE Threads::Threads
)
######################
# Executable targets #
######################
add_executable(fastfetch
src/fastfetch.c
)
target_link_libraries(fastfetch
PRIVATE libfastfetch
)
add_executable(flashfetch
src/flashfetch.c
)
target_link_libraries(flashfetch
PRIVATE libfastfetch
)
###################
# Testing targets #
###################
if (BUILD_TESTS)
add_executable(fastfetch-test-strbuf
tests/strbuf.c
)
target_link_libraries(fastfetch-test-strbuf
PRIVATE libfastfetch
)
enable_testing()
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
endif()
##################
# install target #
##################
#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_ROOT}/etc" CACHE PATH "..." FORCE)
endif()
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")
elseif(APPLE)
set(CPACK_GENERATOR "${CPACK_GENERATOR};DragNDrop")
set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK TRUE)
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)
+36
View File
@@ -0,0 +1,36 @@
# 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
- [ ] Better OS output for all possible combinations of /etc/os-release variables.
- [ ] Find wayland compositor by looking at \${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY:-wayland-0}
- [ ] 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
@@ -0,0 +1,21 @@
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.
+102 -16
View File
@@ -1,29 +1,115 @@
# Fastfetch Benchmark Data
# <center> Fastfetch </center>
This branch stores continuous performance benchmark data for Fastfetch on Linux, macOS, and Windows.
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 and MacOS are supported.
The data is generated and updated automatically by GitHub Actions. Please do not edit generated benchmark files manually.
<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" />
## Benchmark Dashboard
## Customization
<https://fastfetch-cli.github.io/fastfetch/dev/bench/>
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.
## Metrics
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.
The benchmark data includes:
## Dependencies
- Execution time for each Fastfetch module, measured in milliseconds;
- Total Fastfetch process execution time, measured in milliseconds.
Fastfetch dynamically loads needed libraries if they are available. Therefore its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and `libpthread`. They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions, so you probably don't have to worry about it.
All metrics use the “smaller is better” comparison mode.
The following libraries are used if present at runtime:
* [`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 rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
## Update Workflow
## Support status
All categories not listed here should work without needing a specific implementation.
Benchmark data is generated from the `dev` branch CI workflow and updated after all platform build jobs have completed.
##### Available Modules
```
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
```
Related workflow files:
##### Logos
```
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Ubuntu, Void, 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.
* Unknown/unsupported logos will be replaced with a generic linux logo when running fastfetch.
* Get a list of all available logos with `fastfetch --print-logos`.
* Printing images as logo is supported using Sixel or Kitty graphics protocol.
- `.github/workflows/build-benchmark.yml`
- `.github/workflows/ci.yml`
##### Package managers
```
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, brew
```
Commit information and dates are recorded automatically by the Continuous Benchmark Action.
##### WM themes
```
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE)
```
##### DE versions
```
KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
```
##### Terminal fonts
```
konsole, gnome-terminal-server, tilix, xfce4-terminal, alacritty, lxterminal, TTY
```
## Building
fastfetch uses [`cmake`](https://cmake.org/) and [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) for building. 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 pkg-config 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.
## 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
+392
View File
@@ -0,0 +1,392 @@
#!/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"
"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"
"--recache"
"--nocache"
"--show-errors"
"--logo-print-remaining"
"--multithreading"
"--allow-slow-operations"
"--disable-linewrap"
"--hide-cursor"
"--localip-show-ipv4"
"--localip-show-ipv6"
"--localip-show-loop"
"--escape-bedrock"
"--pipe"
"--title-fqdn"
"--escape-bedrock"
)
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"
"--public-ip-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"
"--locale-key"
"--locale-format"
"--locale-error"
"--local-ip-key"
"--local-ip-format"
"--local-ip-error"
"--public-ip-key"
"--public-ip-format"
"--public-ip-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"
)
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
-69572
View File
File diff suppressed because it is too large Load Diff
-405
View File
@@ -1,405 +0,0 @@
<!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-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="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js"></script>
<script src="data.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 total process time for one operating system and architecture. Module curves are available from the legend and hidden by default.</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"></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 && entry.commit.timestamp || entry.date;
const date = new Date(raw);
return {
date: Number.isNaN(date.valueOf()) ? String(entry.date || '') : date.toISOString(),
sha: entry.commit && entry.commit.id ? entry.commit.id : 'unknown'
};
}
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'
];
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 = [];
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);
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 });
}
const familyOrder = ['Intel', 'ARM', 'Other'];
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: metric !== 'total process time'
}))
},
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, metric === 'total process time'));
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 (!groups.size) {
tabs.hidden = true;
panels.innerHTML = '<p class="empty">No benchmark data available.</p>';
}
})();
</script>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Break:Colors
+3
View File
@@ -0,0 +1,3 @@
--logo arch
--os-format "Arch Linux ({12})"
--packages-format "{} (pacman)"
+4
View File
@@ -0,0 +1,4 @@
--disable-linewrap false
--multithreading false
--show-errors
--recache
+3
View File
@@ -0,0 +1,3 @@
--load-config devinfo
--load-config all
--load-config verbose
+1
View File
@@ -0,0 +1 @@
# Load with --load-config examples/1
+24
View File
@@ -0,0 +1,24 @@
# 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
@@ -0,0 +1,7 @@
# 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
@@ -0,0 +1,7 @@
# Load with --load-config examples/4
--color blue
--logo arch_small
--logo-padding-right 1
--separator "  "
--structure Date:Time:Break:Player:Media
+12
View File
@@ -0,0 +1,12 @@
# 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
--font-format {21}
--cursor-key C
+4
View File
@@ -0,0 +1,4 @@
--structure Host:Resolution:CPU:GPU:Memory:Disk:Battery
--memory-format "{?2}{2}MiB{?}"
--disk-format "{?2}{2}GB{?}"
--battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}"
+10
View File
@@ -0,0 +1,10 @@
--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}{-}{/}{}MiB / {}MiB"
--gpu-key "GPU"
--resolution-key "Resolution"
+5
View File
@@ -0,0 +1,5 @@
--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
@@ -0,0 +1 @@
--structure OS:Kernel:Shell:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont
+29
View File
@@ -0,0 +1,29 @@
--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: {}; bios_date: {}; bios_release: {}; bios_vendor: {}; bios_version: {}; board_name: {}; board_vendor: {}; board_version: {}; chassis_type: {}; chassis_vendor: {}; chassis_version: {}; 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: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}
--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 Plasma raw: {}; Plasma name: {}; Plasma size: {}; Plasma styles: {}; Plasma pretty: {}; GTK2 raw: {}; GTK2 name: {}; GTK2 size: {}; GTK2 styles: {}; GTK2 pretty: {}; GTK3 raw: {}; GTK3 name: {}; GTK3 size: {}; GTK3 styles: {}; GTK3 pretty: {}; GTK4 raw: {}; GTK4 name: {}; GTK4 size: {}; GTK4 styles: {}; GTK4 pretty: {}; GTK: {}
--cursor-format Theme: {}; Size: {}
--terminal-format Process: {}; Path: {}; Exe: {}
--terminal-font-format Raw: {}; Name: {}; Size: {}; Styles: {}; Pretty: {}
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
--cpu-usage-format Percentage: {}
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}
--memory-format Used: {}; Total: {}; Percentage: {}
--disk-format Used: {}; Total: {}; Files: {}; Percentage: {}
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
--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: {}
Executable
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env sh
# make the script exit if any of the commands fail,
# making fastfetch not run if the build failed.
set -e
mkdir -p build/
cd build/
cmake ..
cmake --build . --target fastfetch -j$(nproc)
./fastfetch "$@"
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

+234
View File
@@ -0,0 +1,234 @@
#include "fastfetch.h"
#include "common/caching.h"
#include "common/io.h"
#include "common/printing.h"
#include <stdlib.h>
#define FF_CACHE_VERSION_NAME "cacheversion"
#define FF_CACHE_VERSION_EXTENSION "ffv"
#define FF_CACHE_VALUE_EXTENSION "ffcv"
#define FF_CACHE_SPLIT_EXTENSION "ffcs"
#define FF_CACHE_EXTENSION_DATA "ffcd"
static void getCacheFilePath(const FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
{
ffStrbufAppend(buffer, &instance->state.cacheDir);
ffStrbufAppendS(buffer, moduleName);
if(extension != NULL)
{
ffStrbufAppendC(buffer, '.');
ffStrbufAppendS(buffer, extension);
}
}
static void readCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
getCacheFilePath(instance, moduleName, extension, &path);
ffAppendFileBuffer(path.chars, buffer);
ffStrbufDestroy(&path);
}
static void writeCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* content)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
getCacheFilePath(instance, moduleName, extension, &path);
ffWriteFileBuffer(path.chars, content);
ffStrbufDestroy(&path);
}
void ffCacheValidate(FFinstance* instance)
{
FFstrbuf content;
ffStrbufInit(&content);
readCacheFile(instance, FF_CACHE_VERSION_NAME, FF_CACHE_VERSION_EXTENSION, &content);
const char exactVersion[] = FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK;
bool isSameVersion = ffStrbufCompS(&content, exactVersion) == 0;
ffStrbufDestroy(&content);
if(isSameVersion)
return;
instance->config.recache = true;
FFstrbuf version;
ffStrbufInitA(&version, sizeof(exactVersion));
ffStrbufAppendS(&version, exactVersion);
writeCacheFile(instance, FF_CACHE_VERSION_NAME, FF_CACHE_VERSION_EXTENSION, &version);
ffStrbufDestroy(&version);
}
void ffCacheOpenWrite(FFinstance* instance, const char* moduleName, FFcache* cache)
{
FFstrbuf cacheFileValue;
ffStrbufInitA(&cacheFileValue, 64);
getCacheFilePath(instance, moduleName, FF_CACHE_VALUE_EXTENSION, &cacheFileValue);
cache->value = fopen(cacheFileValue.chars, "w");
ffStrbufDestroy(&cacheFileValue);
FFstrbuf cacheFileSplit;
ffStrbufInitA(&cacheFileSplit, 64);
getCacheFilePath(instance, moduleName, FF_CACHE_SPLIT_EXTENSION, &cacheFileSplit);
cache->split = fopen(cacheFileSplit.chars, "w");
ffStrbufDestroy(&cacheFileSplit);
}
void ffCacheClose(FFcache* cache)
{
if(cache->value != NULL)
fclose(cache->value);
if(cache->split != NULL)
fclose(cache->split);
}
static bool printCachedValue(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
readCacheFile(instance, moduleName, FF_CACHE_VALUE_EXTENSION, &content);
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
if(content.length == 0)
return false;
uint8_t moduleCounter = 1;
uint32_t startIndex = 0;
while(startIndex < content.length)
{
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintLogoAndKey(instance, moduleName, moduleIndex, &moduleArgs->key);
puts(content.chars + startIndex);
startIndex = nullByteIndex + 1;
++moduleCounter;
}
ffStrbufDestroy(&content);
return moduleCounter > 1;
}
static bool printCachedFormat(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
readCacheFile(instance, moduleName, FF_CACHE_SPLIT_EXTENSION, &content);
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
if(content.length == 0)
return false;
uint8_t moduleCounter = 1;
FFformatarg* arguments = calloc(numArgs, sizeof(FFformatarg));
uint32_t argumentCounter = 0;
uint32_t startIndex = 0;
while(startIndex < content.length)
{
arguments[argumentCounter].type = FF_FORMAT_ARG_TYPE_STRING;
arguments[argumentCounter].value = &content.chars[startIndex];
++argumentCounter;
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
if(argumentCounter == numArgs)
{
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintFormat(instance, moduleName, moduleIndex, moduleArgs, numArgs, arguments);
++moduleCounter;
argumentCounter = 0;
}
startIndex = nullByteIndex + 1;
}
free(arguments);
ffStrbufDestroy(&content);
return moduleCounter > 1;
}
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs)
{
if(instance->config.recache)
return false;
if(moduleArgs->outputFormat.length == 0)
return printCachedValue(instance, moduleName, moduleArgs);
else
return printCachedFormat(instance, moduleName, moduleArgs, numArgs);
}
void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFcache* cache, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments)
{
if(moduleArgs->outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, &moduleArgs->key);
ffStrbufPutTo(value, stdout);
}
else
{
ffPrintFormat(instance, moduleName, moduleIndex, moduleArgs, numArgs, arguments);
}
if(cache->value != NULL)
{
ffStrbufWriteTo(value, cache->value);
fputc('\0', cache->value);
}
if(cache->split == NULL)
return;
for(uint32_t i = 0; i < numArgs; i++)
{
FFstrbuf buffer;
ffStrbufInitA(&buffer, 64);
ffFormatAppendFormatArg(&buffer, &arguments[i]);
ffStrbufWriteTo(&buffer, cache->split);
ffStrbufDestroy(&buffer);
fputc('\0', cache->split);
}
}
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments)
{
FFcache cache;
ffCacheOpenWrite(instance, moduleName, &cache);
ffPrintAndAppendToCache(instance, moduleName, 0, moduleArgs, &cache, value, numArgs, arguments);
ffCacheClose(&cache);
}
void ffCachingWriteData(const FFinstance* instance, const char* moduleName, size_t dataSize, const void* data)
{
FFstrbuf path;
ffStrbufInitA(&path, 128);
getCacheFilePath(instance, moduleName, FF_CACHE_EXTENSION_DATA, &path);
ffWriteFileData(path.chars, dataSize, data);
ffStrbufDestroy(&path);
}
bool ffCachingReadData(const FFinstance* instance, const char* moduleName, size_t dataSize, void* data)
{
if(instance->config.recache)
return false;
FFstrbuf path;
ffStrbufInitA(&path, 128);
getCacheFilePath(instance, moduleName, FF_CACHE_EXTENSION_DATA, &path);
ssize_t result = ffReadFileData(path.chars, dataSize, data);
ffStrbufDestroy(&path);
return result > 0 && (size_t) result == dataSize;
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#ifndef FF_INCLUDED_common_caching
#define FF_INCLUDED_common_caching
#include "fastfetch.h"
#include "common/format.h"
typedef struct FFcache
{
FILE* value;
FILE* split;
} FFcache;
void ffCacheValidate(FFinstance* instance);
void ffCacheOpenWrite(FFinstance* instance, const char* moduleName, FFcache* cache);
void ffCacheClose(FFcache* cache);
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs);
void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFcache* cache, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments);
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments);
void ffCachingWriteData(const FFinstance* instance, const char* moduleName, size_t dataSize, const void* data);
bool ffCachingReadData(const FFinstance* instance, const char* moduleName, size_t dataSize, void* data);
#endif
+216
View File
@@ -0,0 +1,216 @@
#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 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);
}
+23
View File
@@ -0,0 +1,23 @@
#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 ffFontDestroy(FFfont* font);
#endif
+258
View File
@@ -0,0 +1,258 @@
#include "fastfetch.h"
#include "common/format.h"
#include "common/parsing.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, "%u", *(uint32_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
ffStrbufAppendF(buffer, "%hu", *(uint16_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
ffStrbufAppendF(buffer, "%hhu", *(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_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);
}
}
static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
{
uint32_t result = UINT32_MAX;
if(placeholderValue->chars[0] != '-')
sscanf(placeholderValue->chars, "%u", &result);
return 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)++]);
}
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)
);
}
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);
}
+28
View File
@@ -0,0 +1,28 @@
#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
} 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);
#endif
+451
View File
@@ -0,0 +1,451 @@
#include "fastfetch.h"
#include "common/caching.h"
#include "common/parsing.h"
#include "detection/qt.h"
#include "detection/gtk.h"
#include "detection/displayserver/displayserver.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <pthread.h>
static bool strbufEqualsAdapter(const void* first, const void* second)
{
return ffStrbufComp(second, first) == 0;
}
static void initConfigDirs(FFstate* state)
{
ffListInit(&state->configDirs, sizeof(FFstrbuf));
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
if(ffStrSet(xdgConfigHome))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigHome);
ffStrbufEnsureEndsWithC(buffer, '/');
}
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
if(ffListFirstIndexComp(&state->configDirs, element, strbufEqualsAdapter) < 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)
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;
}
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfigHome, 64);
ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ROOT"/etc/xdg/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome)
FFstrbuf* systemConfig = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfig, 64);
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ROOT"/etc/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
}
static void initCacheDir(FFstate* state)
{
ffStrbufInitA(&state->cacheDir, 64);
ffStrbufAppendS(&state->cacheDir, getenv("XDG_CACHE_HOME"));
if(state->cacheDir.length == 0)
{
ffStrbufAppendS(&state->cacheDir, state->passwd->pw_dir);
ffStrbufAppendS(&state->cacheDir, "/.cache/");
}
else
ffStrbufEnsureEndsWithC(&state->cacheDir, '/');
mkdir(state->cacheDir.chars, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a cache folder, but who knows
ffStrbufAppendS(&state->cacheDir, "fastfetch/");
mkdir(state->cacheDir.chars, S_IRWXU | S_IRGRP | S_IROTH);
}
static void initState(FFstate* state)
{
state->logoWidth = 0;
state->logoHeight = 0;
state->keysHeight = 0;
state->passwd = getpwuid(getuid());
uname(&state->utsname);
#if FF_HAVE_SYSINFO_H
sysinfo(&state->sysinfo);
#endif
initConfigDirs(state);
initCacheDir(state);
}
static void initModuleArg(FFModuleArgs* args)
{
ffStrbufInitA(&args->key, 0);
ffStrbufInitA(&args->outputFormat, 0);
ffStrbufInitA(&args->errorFormat, 0);
}
static void defaultConfig(FFinstance* instance)
{
ffStrbufInit(&instance->config.logo.source);
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;
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.cacheSave = true;
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;
initModuleArg(&instance->config.os);
initModuleArg(&instance->config.host);
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.locale);
initModuleArg(&instance->config.localIP);
initModuleArg(&instance->config.publicIP);
initModuleArg(&instance->config.player);
initModuleArg(&instance->config.song);
initModuleArg(&instance->config.dateTime);
initModuleArg(&instance->config.date);
initModuleArg(&instance->config.time);
initModuleArg(&instance->config.vulkan);
initModuleArg(&instance->config.openGL);
initModuleArg(&instance->config.openCL);
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);
instance->config.titleFQDN = false;
ffStrbufInitA(&instance->config.diskFolders, 0);
ffStrbufInitA(&instance->config.batteryDir, 0);
ffStrbufInitA(&instance->config.separatorString, 0);
instance->config.localIpShowIpV4 = true;
instance->config.localIpShowIpV6 = false;
instance->config.localIpShowLoop = false;
instance->config.publicIpTimeout = 0;
ffStrbufInitA(&instance->config.osFile, 0);
ffStrbufInitA(&instance->config.playerName, 0);
}
void ffInitInstance(FFinstance* instance)
{
initState(&instance->state);
defaultConfig(instance);
}
#if !defined(__ANDROID__)
static void* connectDisplayServerThreadMain(void* instance)
{
ffConnectDisplayServer((FFinstance*)instance);
return NULL;
}
#if !defined(__APPLE__)
static void* detectPlasmaThreadMain(void* instance)
{
ffDetectQt((FFinstance*)instance);
return NULL;
}
static void* detectGTK2ThreadMain(void* instance)
{
ffDetectGTK2((FFinstance*)instance);
return NULL;
}
static void* detectGTK3ThreadMain(void* instance)
{
ffDetectGTK3((FFinstance*)instance);
return NULL;
}
static void* detectGTK4ThreadMain(void* instance)
{
ffDetectGTK4((FFinstance*)instance);
return NULL;
}
static void* startThreadsThreadMain(void* instance)
{
pthread_t dsThread;
pthread_create(&dsThread, NULL, connectDisplayServerThreadMain, instance);
pthread_detach(dsThread);
pthread_t gtk2Thread;
pthread_create(&gtk2Thread, NULL, detectGTK2ThreadMain, instance);
pthread_detach(gtk2Thread);
pthread_t gtk3Thread;
pthread_create(&gtk3Thread, NULL, detectGTK3ThreadMain, instance);
pthread_detach(gtk3Thread);
pthread_t gtk4Thread;
pthread_create(&gtk4Thread, NULL, detectGTK4ThreadMain, instance);
pthread_detach(gtk4Thread);
pthread_t plasmaThread;
pthread_create(&plasmaThread, NULL, detectPlasmaThreadMain, instance);
pthread_detach(plasmaThread);
return NULL;
}
void startDetectionThreads(FFinstance* instance)
{
pthread_t startThreadsThread;
pthread_create(&startThreadsThread, NULL, startThreadsThreadMain, instance);
pthread_detach(startThreadsThread);
}
#else // !__APPLE__
void startDetectionThreads(FFinstance* instance)
{
pthread_t startThreadsThread;
pthread_create(&startThreadsThread, NULL, connectDisplayServerThreadMain, instance);
pthread_detach(startThreadsThread);
}
#endif // __APPLE__
#else // !__ANDROID__
void startDetectionThreads(FFinstance* instance)
{
FF_UNUSED(instance);
}
#endif // __ANDROID__
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);
}
static void exitSignalHandler(int signal)
{
FF_UNUSED(signal);
resetConsole();
exit(0);
}
void ffStart(FFinstance* instance)
{
if(instance->config.multithreading)
startDetectionThreads(instance);
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
struct sigaction action = {};
action.sa_handler = exitSignalHandler;
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
sigaction(SIGQUIT, &action, NULL);
//We do the cache validation here, so we can skip it if --recache is given
if(!instance->config.recache)
ffCacheValidate(instance);
//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();
}
//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
""
, stdout);
}
+192
View File
@@ -0,0 +1,192 @@
#include "fastfetch.h"
#include "common/io.h"
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
static void createSubfolders(const char* fileName)
{
FFstrbuf path;
ffStrbufInit(&path);
while(*fileName != '\0')
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
++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)
{
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);
return ret;
}
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
{
return ffWriteFileData(fileName, buffer->length, buffer->chars);
}
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
{
ssize_t readed = 0;
ffStrbufEnsureFree(buffer, 31); // 32 - 1 for the null terminator
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)
{
int fd = open(fileName, O_RDONLY);
if(fd == -1)
return -1;
ssize_t readed = read(fd, data, dataSize);
close(fd);
return readed;
}
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
{
int fd = open(fileName, O_RDONLY);
if(fd == -1)
return false;
bool ret = ffAppendFDBuffer(fd, buffer);
close(fd);
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, ...)
{
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);
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#ifndef FF_INCLUDED_common_io
#define FF_INCLUDED_common_io
#include <sys/types.h> //mode_t
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);
bool ffFileExists(const char* fileName, mode_t mode);
// Not thread safe!
void ffSuppressIO(bool suppress);
void ffGetTerminalResponse(const char* request, const char* format, ...);
#endif
+56
View File
@@ -0,0 +1,56 @@
#include "fastfetch.h"
#include "common/library.h"
#include <stdarg.h>
static void* libraryLoad(const char* path, int maxVersion)
{
void* result = dlopen(path, RTLD_LAZY);
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, RTLD_LAZY);
if(result != NULL)
break;
ffStrbufSubstrBefore(&pathbuf, originalLength);
}
ffStrbufDestroy(&pathbuf);
return result;
}
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...)
{
if(userProvidedName->length > 0)
return dlopen(userProvidedName->chars, RTLD_LAZY);
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;
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#ifndef FF_INCLUDED_common_library
#define FF_INCLUDED_common_library
#include <dlfcn.h>
#ifdef __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_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
+69
View File
@@ -0,0 +1,69 @@
#include "fastfetch.h"
#include "common/networking.h"
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, FFstrbuf* buffer)
{
struct addrinfo hints = {0};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo* addr;
if(getaddrinfo(host, "80", &hints, &addr) != 0)
return;
int sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(sock == -1)
{
freeaddrinfo(addr);
return;
}
if(timeout > 0)
{
struct timeval timev;
timev.tv_sec = 0;
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
}
if(connect(sock, addr->ai_addr, addr->ai_addrlen) == -1)
{
close(sock);
freeaddrinfo(addr);
return;
}
freeaddrinfo(addr);
FFstrbuf command;
ffStrbufInitA(&command, 64);
ffStrbufAppendS(&command, "GET ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&command, host);
ffStrbufAppendS(&command, "\r\n\r\n");
if(send(sock, command.chars, command.length, 0) == -1)
{
ffStrbufDestroy(&command);
close(sock);
return;
}
ssize_t received = recv(sock, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
if(received > 0)
{
buffer->length += (uint32_t) received;
buffer->chars[buffer->length] = '\0';
}
ffStrbufDestroy(&command);
close(sock);
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#ifndef FF_INCLUDED_common_networking
#define FF_INCLUDED_common_networking
#include "util/FFstrbuf.h"
void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, FFstrbuf* buffer);
#endif
+177
View File
@@ -0,0 +1,177 @@
#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
@@ -0,0 +1,26 @@
#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
+163
View File
@@ -0,0 +1,163 @@
#include "fastfetch.h"
#include "common/printing.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)
puts(FASTFETCH_TEXT_MODIFIER_RESET);
}
}
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)
{
for(uint32_t i = 0; i < times; i++)
putchar(c);
}
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
@@ -0,0 +1,18 @@
#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);
void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...);
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
+36
View File
@@ -0,0 +1,36 @@
#include "fastfetch.h"
#include "common/processing.h"
#include "common/io.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
{
int pipes[2];
if(pipe(pipes) == -1)
return;
pid_t childPid = fork();
if(childPid == -1)
return;
//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]);
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#ifndef FF_INCLUDED_common_processing
#define FF_INCLUDED_common_processing
#include "util/FFstrbuf.h"
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
#endif
+207
View File
@@ -0,0 +1,207 @@
#include "fastfetch.h"
#include "common/properties.h"
#include <stdlib.h>
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
@@ -0,0 +1,23 @@
#pragma once
#ifndef FF_INCLUDED_common_properties
#define FF_INCLUDED_common_properties
#include "util/FFstrbuf.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
+395
View File
@@ -0,0 +1,395 @@
#include "fastfetch.h"
#include "common/settings.h"
#include "common/library.h"
#include "common/io.h"
#include <pthread.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 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
pthread_mutex_lock(&mutex); \
if(initState != FF_INITSTATE_UNINITIALIZED) {\
pthread_mutex_unlock(&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; \
pthread_mutex_unlock(&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; \
pthread_mutex_unlock(&mutex); \
return NULL; \
}
#define FF_LIBRARY_DATA_LOAD_RETURN \
initState = FF_INITSTATE_SUCCESSFUL; \
pthread_mutex_unlock(&mutex); \
return &data;
#define FF_LIBRARY_DATA_LOAD_ERROR \
{ \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
pthread_mutex_unlock(&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(FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0.so", 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(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(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(FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf.so", 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(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(FFinstance* instance, const char* key, FFvarianttype type)
{
FF_UNUSED(instance, key, type)
return FF_VARIANT_NULL;
}
#endif //FF_HAVE_DCONF
FFvariant ffSettingsGet(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(FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0.so", 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(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(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>
#include <sys/stat.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.so", 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__
#ifdef __APPLE__
#include <sys/sysctl.h>
void ffSettingsGetAppleProperty(const char* propName, FFstrbuf* result)
{
size_t neededLength;
if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 0)
return;
ffStrbufEnsureFree(result, (uint32_t) neededLength);
if(sysctlbyname(propName, result->chars + result->length, &neededLength, NULL, 0) == 0)
result->length += (uint32_t) neededLength;
result->chars[result->length] = '\0';
}
int ffSettingsGetAppleInt(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 ffSettingsGetAppleInt64(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;
}
#endif //__APPLE__
+45
View File
@@ -0,0 +1,45 @@
#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(FFinstance* instance, const char* key, FFvarianttype type);
FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type);
FFvariant ffSettingsGet(FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
FFvariant ffSettingsGetXFConf(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
#ifdef __APPLE__
void ffSettingsGetAppleProperty(const char* propName, FFstrbuf* result);
int ffSettingsGetAppleInt(const char* propName, int defaultValue);
int64_t ffSettingsGetAppleInt64(const char* propName, int64_t defaultValue);
#endif
#endif
+16
View File
@@ -0,0 +1,16 @@
# 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
+322
View File
@@ -0,0 +1,322 @@
# 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
# 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, 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 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
# OS file option
# Sets the path to the file containing the operating system information.
# Should be a valid path to an existing file.
# Note that you might need to run fastfetch with --recache once for it to take affect.
# 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
# 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
#--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}
#--locale-key Locale
#--local-ip-key Local IP ({1})
#--public-ip-key Public IP
#--player-key Media Player
#--song-key Song
#--datetime-key Date Time
#--vulkan-key Vulkan
#--opengl-key OpenGL
#--opencl-key OpenCL
# 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
#--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
#--locale-format
#--local-ip-format
#--public-ip-format
#--player-format
#--song-format
#--datetime-format
#--vulkan-format
#--opengl-format
#--opencl-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
#--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
#--locale-error
#--local-ip-error
#--public-ip-error
#--player-error
#--song-error
#--datetime-error
#--vulkan-error
#--opengl-error
#--opencl-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
#--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
+104
View File
@@ -0,0 +1,104 @@
Usage: fastfetch <options>
Informative options:
-h,--help: shows this message and exits
-h,--help <command>: shows help for a specific command and exits
-v,--version: prints the version of fastfetch and exits
--list-logos: list available logos and exits
--list-modules: lists available modules and exits
--list-presets: list presets fastfetch knows about and exits. They can be loaded with --load-config. (+)
--list-features: list the supported features fastfetch was compiled with and exits. Mainly for development.
--print-logos: show available logos and exits
--print-config-system: prints the default system config and exits
--print-config-user: prints the default user config and exits
--print-structure: prints the default stucture and exits
General options:
-r,--recache <?value>: generate new cached values
--nocache <?value>: don't use cached values, but also don't overwrite existing ones
--load-config <file>: load a config file or a preset (+)
--multithreading <?value>: use multiple threads to detect values
--allow-slow-operations <?value>: allow operations that are usually very slow for more detailed output
--escape-bedrock <?value>: on bedrock linux, sets if it should escape the bedrock jail or not
--pipe <?value>: disable logo and all escape sequences
Logo options:
-l,--logo <logo>: set the logo to use. The type is specified by --logo-type. 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, raw, sixel, kitty or chafa.
--logo-width <width>: set the width of the logo (in characters), if it is an image
--logo-height <height>: set the height of the logo (in characters), if it is an image
--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>: weather to print the remaining logo, if it has more lines than modules to display
--sixel <file>: short for --logo-type sixel --logo <file>
--kitty <file>: short for --logo-type kitty --logo <file>
--chafa <file>: short for --logo-type chafa --logo <file>
--file <file>: short for --logo-type file --logo <file>
--raw <file>: short for --logo-type raw --logo <file>
Display options:
-s,--structure <structure>: sets 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>: sers the color of the keys
--color-title <color>: sets the color of the title
-c,--color <color>: sets the color of both the keys and the title
--separator <str>: sets 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 occuring errors
--disable-linewrap <?value>: weather to disable linewrap during the run
--hide-cursor <?value>: weather to hide the cursor during the run
--binary-prefix <value>: sets the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC
General module options:
--<module>-format <format>: Sets 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>: Sets 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>: Sets 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>
Module specific options:
--title-fqdn <?value>: sets 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 informations
--disk-folders <folders>: A colon separated list of folder paths for the disk output. Default is "/:/home"
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--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
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--player-name: The name of the player to use
--gl <value>: Sets the opengl context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
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
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,36 @@
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".
+39
View File
@@ -0,0 +1,39 @@
Battery
Break
Colors
CPU
CPUUsage
Cursor
Date
Datetime
DE
Disk
Font
GPU
Host
Icons
Kernel
Locale
LocalIP
Media
Memory
OS
OpenCL
OpenGL
Packages
Player
Processes
PublicIP
Resolution
Separator
Shell
Swap
Terminal
TerminalFont
Theme
Time
Title
Uptime
Vulkan
WM
WMTheme
+1
View File
@@ -0,0 +1 @@
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors
+22
View File
@@ -0,0 +1,22 @@
#include "cpu.h"
#include "detection/internal.h"
void ffDetectCPUImpl(FFCPUResult* cpu);
const FFCPUResult* ffDetectCPU()
{
FF_DETECTION_INTERNAL_GUARD(FFCPUResult,
ffDetectCPUImpl(&result);
const char* removeStrings[] = {
"(R)", "(r)", "(TM)", "(tm)",
" 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(&result.name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
ffStrbufSubstrBeforeFirstC(&result.name, '@'); //Cut the speed output in the name as we append our own
ffStrbufTrimRight(&result.name, ' '); //If we removed the @ in previous step there was most likely a space before it
);
}
+27
View File
@@ -0,0 +1,27 @@
#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();
#endif
+42
View File
@@ -0,0 +1,42 @@
#include "cpu.h"
#include "common/settings.h"
static double getFrequency(const char* propName)
{
double herz = (double) ffSettingsGetAppleInt64(propName, 0);
if(herz <= 0.0)
return herz;
herz /= 1000.0; //to KHz
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
}
void ffDetectCPUImpl(FFCPUResult* cpu)
{
ffStrbufInit(&cpu->name);
ffSettingsGetAppleProperty("machdep.cpu.brand_string", &cpu->name);
ffStrbufInit(&cpu->vendor);
ffSettingsGetAppleProperty("machdep.cpu.vendor", &cpu->vendor);
cpu->coresPhysical = (uint16_t) ffSettingsGetAppleInt("hw.physicalcpu_max", 1);
if(cpu->coresPhysical == 1)
cpu->coresPhysical = (uint16_t) ffSettingsGetAppleInt("hw.physicalcpu", 1);
cpu->coresLogical = (uint16_t) ffSettingsGetAppleInt("hw.logicalcpu_max", 1);
if(cpu->coresLogical == 1)
cpu->coresLogical = (uint16_t) ffSettingsGetAppleInt("hw.ncpu", 1);
cpu->coresOnline = (uint16_t) ffSettingsGetAppleInt("hw.logicalcpu", 1);
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSettingsGetAppleInt("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");
//TODO find a way to detect this
cpu->temperature = FF_CPU_TEMP_UNSET;
}
+102
View File
@@ -0,0 +1,102 @@
#include "cpu.h"
#include "common/io.h"
#include "common/properties.h"
#include "detection/temps.h"
#include <stdlib.h>
#include <unistd.h>
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer)
{
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) ||
(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);
ffReadFileBuffer(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
}
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 FFTempsResult *temps = ffDetectTemps();
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(FFCPUResult* cpu)
{
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
FFstrbuf physicalCoresBuffer;
ffStrbufInit(&physicalCoresBuffer);
parseCpuInfo(cpu, &physicalCoresBuffer);
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/"
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
cpu->temperature = detectCPUTemp();
ffStrbufDestroy(&physicalCoresBuffer);
}
+73
View File
@@ -0,0 +1,73 @@
#include "fastfetch.h"
#include "detection/datetime.h"
#include <time.h>
#include <pthread.h>
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
{
FF_UNUSED(instance); //We may need it later for additional configuration
static FFDateTimeResult result;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static bool init = false;
pthread_mutex_lock(&mutex);
if (init)
{
pthread_mutex_unlock(&mutex);
return &result;
}
init = true;
const time_t t = time(NULL);
struct tm* tm = localtime(&t);
result.year = (uint16_t) (tm->tm_year + 1900);
result.yearShort = (uint8_t) (result.year % 100);
result.month = (uint8_t) (tm->tm_mon + 1);
ffStrbufInit(&result.monthPretty);
result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm);
ffStrbufInit(&result.monthName);
result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm);
ffStrbufInit(&result.monthNameShort);
result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm);
result.week = (uint8_t) (tm->tm_yday / 7 + 1);
ffStrbufInit(&result.weekday);
result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm);
ffStrbufInit(&result.weekdayShort);
result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm);
result.dayInYear = (uint8_t) (tm->tm_yday + 1);
result.dayInMonth = (uint8_t) tm->tm_mday;
result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday;
result.hour = (uint8_t) tm->tm_hour;
ffStrbufInit(&result.hourPretty);
result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm);
result.hour12 = (uint8_t) (result.hour % 12);
ffStrbufInit(&result.hour12Pretty);
result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm);
result.minute = (uint8_t) tm->tm_min;
ffStrbufInit(&result.minutePretty);
result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm);
result.second = (uint8_t) tm->tm_sec;
ffStrbufInit(&result.secondPretty);
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm);
pthread_mutex_unlock(&mutex);
return &result;
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#ifndef FF_INCLUDED_detection_datetime
#define FF_INCLUDED_detection_datetime
#include "fastfetch.h"
typedef struct FFDateTimeResult
{
//Examples for 21.02.2022 - 15:18:37
uint16_t year; //2022
uint8_t yearShort; //22
uint8_t month; //2
FFstrbuf monthPretty; //02
FFstrbuf monthName; //February
FFstrbuf monthNameShort; //Feb
uint8_t week; //8
FFstrbuf weekday; //Monday
FFstrbuf weekdayShort; //Mon
uint16_t dayInYear; //52
uint8_t dayInMonth; //21
uint8_t dayInWeek; //1
uint8_t hour; //15
FFstrbuf hourPretty; //15
uint8_t hour12; //3
FFstrbuf hour12Pretty; //03
uint8_t minute; //18
FFstrbuf minutePretty; //18
uint8_t second; //37
FFstrbuf secondPretty; //37
} FFDateTimeResult;
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance);
#endif
@@ -0,0 +1,42 @@
#include "displayserver.h"
#include "detection/internal.h"
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
{
if(refreshRate <= 0)
return 0;
int remainder = refreshRate % 5;
if(remainder >= 3)
refreshRate += (5 - remainder);
else
refreshRate -= remainder;
//All other typicall refresh rates are dividable by 5
if(refreshRate == 145)
refreshRate = 144;
return (uint32_t) refreshRate;
}
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate)
{
if(width == 0 || height == 0)
return false;
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
resolution->width = width;
resolution->height = height;
resolution->refreshRate = refreshRate;
return true;
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance);
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance)
{
FF_DETECTION_INTERNAL_GUARD(FFDisplayServerResult,
ffConnectDisplayServerImpl(&result, instance);
);
}
@@ -0,0 +1,32 @@
#pragma once
#ifndef FF_INCLUDED_detection_displayserver
#define FF_INCLUDED_detection_displayserver
#include "fastfetch.h"
typedef struct FFResolutionResult
{
uint32_t width;
uint32_t height;
uint32_t refreshRate;
} FFResolutionResult;
typedef struct FFDisplayServerResult
{
FFstrbuf wmProcessName;
FFstrbuf wmPrettyName;
FFstrbuf wmProtocolName;
FFstrbuf deProcessName;
FFstrbuf dePrettyName;
FFstrbuf deVersion;
FFlist resolutions; //List of FFResolutionResult
} FFDisplayServerResult;
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance);
//Used internal
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate);
#endif
@@ -0,0 +1,14 @@
#include "displayserver.h"
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
FF_UNUSED(instance);
ffStrbufInitA(&ds->wmProcessName, 0);
ffStrbufInitA(&ds->wmPrettyName, 0);
ffStrbufInitA(&ds->wmProtocolName, 0);
ffStrbufInitA(&ds->deProcessName, 0);
ffStrbufInitA(&ds->dePrettyName, 0);
ffStrbufInitA(&ds->deVersion, 0);
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 0);
}
@@ -0,0 +1,120 @@
#include "displayserver.h"
#include "common/library.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/sysctl.h>
#include <ApplicationServices/ApplicationServices.h>
//Resolution code heavily inspired by displayplacer <3
typedef union
{
uint8_t rawData[0xDC];
struct
{
uint32_t mode;
uint32_t flags; // 0x4
uint32_t width; // 0x8
uint32_t height; // 0xC
uint32_t depth; // 0x10
uint32_t dc2[42];
uint16_t dc3;
uint16_t freq; // 0xBC
uint32_t dc4[4];
float density; // 0xD0
} derived;
} modes_D4;
void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID display, int idx, modes_D4* mode, int length);
static void detectResolution(FFDisplayServerResult* ds)
{
CGDisplayCount screenCount;
CGGetOnlineDisplayList(INT_MAX, NULL, &screenCount);
if(screenCount == 0)
return;
CGDirectDisplayID* screens = malloc(screenCount * sizeof(CGDirectDisplayID));
CGGetOnlineDisplayList(INT_MAX, screens, &screenCount);
for(uint32_t i = 0; i < screenCount; i++)
{
int modeID;
CGSGetCurrentDisplayMode(screens[i], &modeID);
modes_D4 mode;
CGSGetDisplayModeDescriptionOfLength(screens[i], modeID, &mode, 0xD4);
uint32_t refreshRate = ffdsParseRefreshRate(mode.derived.freq);
ffdsAppendResolution(ds, mode.derived.width, mode.derived.height, refreshRate);
}
free(screens);
}
static void detectWM(FFDisplayServerResult* ds)
{
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
u_int requestLength = sizeof(request) / sizeof(*request);
size_t length = 0;
if(sysctl(request, requestLength, NULL, &length, NULL, 0) != 0)
return;
struct kinfo_proc* processes = malloc(length);
if(processes == NULL)
return;
if(sysctl(request, requestLength, processes, &length, NULL, 0) != 0)
{
free(processes);
return;
}
for(size_t i = 0; i < length / sizeof(struct kinfo_proc); i++)
{
const char* comm = processes[i].kp_proc.p_comm;
if(
strcasecmp(comm, "spectacle") != 0 &&
strcasecmp(comm, "amethyst") != 0 &&
strcasecmp(comm, "kwm") != 0 &&
strcasecmp(comm, "chunkwm") != 0 &&
strcasecmp(comm, "yabai") != 0 &&
strcasecmp(comm, "rectangle") != 0
) continue;
ffStrbufAppendS(&ds->wmProcessName, comm);
ffStrbufAppendS(&ds->wmPrettyName, comm);
ds->wmPrettyName.chars[0] = (char) toupper(ds->wmPrettyName.chars[0]);
break;
}
free(processes);
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
FF_UNUSED(instance);
ffStrbufInit(&ds->wmProcessName);
ffStrbufInit(&ds->wmPrettyName);
ffStrbufInitA(&ds->wmProtocolName, 0);
detectWM(ds);
if(ds->wmProcessName.length == 0)
{
ffStrbufAppendS(&ds->wmProcessName, "quartz");
ffStrbufAppendS(&ds->wmPrettyName, "Quartz Compositor");
}
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInitA(&ds->deVersion, 0);
ffStrbufAppendS(&ds->deProcessName, "aqua");
ffStrbufAppendS(&ds->dePrettyName, "Aqua");
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
detectResolution(ds);
}
@@ -0,0 +1,86 @@
#include "displayserver_linux.h"
#include <dirent.h>
static void parseDRM(FFDisplayServerResult* result)
{
const char* drmDirPath = "/sys/class/drm/";
DIR* dirp = opendir(drmDirPath);
if(dirp == NULL)
return;
FFstrbuf drmDir;
ffStrbufInitA(&drmDir, 64);
ffStrbufAppendS(&drmDir, drmDirPath);
uint32_t drmDirLength = drmDir.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
ffStrbufAppendS(&drmDir, entry->d_name);
ffStrbufAppendS(&drmDir, "/modes");
FILE* modeFile = fopen(drmDir.chars, "r");
if(modeFile == NULL)
{
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
}
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
resolution->width = 0;
resolution->height = 0;
resolution->refreshRate = 0;
int scanned = fscanf(modeFile, "%ix%i", &resolution->width, &resolution->height);
if(scanned < 2 || resolution->width == 0 || resolution->height == 0)
--result->resolutions.length;
fclose(modeFile);
ffStrbufSubstrBefore(&drmDir, drmDirLength);
}
closedir(dirp);
ffStrbufDestroy(&drmDir);
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
ffStrbufInit(&ds->wmProcessName);
ffStrbufInit(&ds->wmPrettyName);
ffStrbufInit(&ds->wmProtocolName);
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
//We try wayland as our prefered display server, as it supports the most features.
//This method can't detect the name of our WM / DE
ffdsConnectWayland(instance, ds);
//Try the x11 libs, from most feature rich to least.
//We use the resolution list to detect if a connection is needed.
//They respect wmProtocolName, and only detect resolution if it is set.
if(ds->resolutions.length == 0)
ffdsConnectXcbRandr(instance, ds);
if(ds->resolutions.length == 0)
ffdsConnectXrandr(instance, ds);
if(ds->resolutions.length == 0)
ffdsConnectXcb(instance, ds);
if(ds->resolutions.length == 0)
ffdsConnectXlib(instance, ds);
//This resolution detection method is display server independent.
//Use it if all connections failed
if(ds->resolutions.length == 0)
parseDRM(ds);
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(instance, ds);
}
@@ -0,0 +1,22 @@
#pragma once
#ifndef FASTFETCH_INCLUDED_DISPLAYSERVER
#define FASTFETCH_INCLUDED_DISPLAYSERVER
#include "detection/displayserver/displayserver.h"
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result);
#endif
+181
View File
@@ -0,0 +1,181 @@
#define _GNU_SOURCE //required for struct ucred
#include "displayserver_linux.h"
#include <stdlib.h>
#include <string.h>
#ifdef FF_HAVE_WAYLAND
#include "common/library.h"
#include "common/io.h"
#include <pthread.h>
#include <wayland-client.h>
#include <sys/socket.h>
typedef struct WaylandData
{
FFlist* results;
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
const struct wl_interface* ffwl_output_interface;
} WaylandData;
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
{
struct ucred ucred;
socklen_t len = sizeof(struct ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
return;
FFstrbuf procPath;
ffStrbufInit(&procPath);
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
ffReadFileBuffer(procPath.chars, &result->wmProcessName);
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
ffStrbufDestroy(&procPath);
}
static void stubListener(void* data, ...)
{
(void) data;
}
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
{
FF_UNUSED(output);
WaylandData* wldata = data;
if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0)
return;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
FFResolutionResult* result = ffListAdd(wldata->results);
pthread_mutex_unlock(&mutex);
result->width = (uint32_t) width;
result->height = (uint32_t) height;
result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000);
}
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
{
WaylandData* wldata = data;
if(strcmp(interface, wldata->ffwl_output_interface->name) == 0)
{
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
if(output == NULL)
return;
//Needs to be static, because the scope of the function will already be lost when calling the listener
static struct wl_output_listener outputListener = {
.mode = waylandOutputModeListener,
.geometry = (void*) stubListener,
//https://lists.freedesktop.org/archives/wayland-devel/2013-July/010278.html
#if WAYLAND_VERSION_MINOR >= 2
.done = (void*) stubListener,
.scale = (void*) stubListener,
#endif
//https://lists.freedesktop.org/archives/wayland-devel/2021-December/042064.html
#if WAYLAND_VERSION_MINOR >= 20
.name = (void*) stubListener,
.description = (void*) stubListener,
#endif
};
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, data);
}
}
bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(wayland, instance->config.libWayland, false, "libwayland-client.so", 1)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
WaylandData data;
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false)
struct wl_display* display = ffwl_display_connect(NULL);
if(display == NULL)
{
dlclose(wayland);
return false;
}
waylandDetectWM(ffwl_display_get_fd(display), result);
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
if(registry == NULL)
{
ffwl_display_disconnect(display);
dlclose(wayland);
return false;
}
data.results = &result->resolutions;
struct wl_registry_listener registry_listener = {
.global = waylandGlobalAddListener,
.global_remove = (void*) stubListener
};
data.ffwl_proxy_add_listener(registry, (void(**)(void)) &registry_listener, &data);
ffwl_display_dispatch(display);
ffwl_display_roundtrip(display);
ffwl_display_disconnect(display); //This will also destroy our wl_registry and wl_output proxies
dlclose(wayland);
//We successfully connected to wayland and detected the resolution.
//So we can set set the session type to wayland.
//This is used as an indicator that we are running wayland by the x11 backends.
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
return true;
}
#endif
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result)
{
//Wayland requires this to be set
if(getenv("XDG_RUNTIME_DIR") == NULL)
return;
#ifdef FF_HAVE_WAYLAND
if(detectWayland(instance, result))
return;
#else
FF_UNUSED(instance);
#endif
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
//If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session.
if(xdgSessionType != NULL && strcasecmp(xdgSessionType, "wayland") != 0)
return;
//If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY or WAYLAND_SOCKET is set.
//If not, there is no indicator for a wayland session
if(xdgSessionType == NULL && getenv("WAYLAND_DISPLAY") == NULL && getenv("WAYLAND_SOCKET") == NULL)
return;
//We are probably running a wayland compositor at this point,
//but fastfetch was compiled without the required library, or loading the library failed.
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
}
+461
View File
@@ -0,0 +1,461 @@
#include "displayserver_linux.h"
#include "common/io.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "common/processing.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
static const char* parseEnv()
{
const char* env;
env = getenv("XDG_CURRENT_DESKTOP");
if(ffStrSet(env))
return env;
env = getenv("XDG_SESSION_DESKTOP");
if(ffStrSet(env))
return env;
env = getenv("CURRENT_DESKTOP");
if(ffStrSet(env))
return env;
env = getenv("SESSION_DESKTOP");
if(ffStrSet(env))
return env;
env = getenv("DESKTOP_SESSION");
if(ffStrSet(env))
return env;
if(getenv("KDE_FULL_SESSION") != NULL || getenv("KDE_SESSION_UID") != NULL || getenv("KDE_SESSION_VERSION") != NULL)
return "KDE";
if(getenv("GNOME_DESKTOP_SESSION_ID") != NULL)
return "Gnome";
if(getenv("MATE_DESKTOP_SESSION_ID") != NULL)
return "Mate";
if(getenv("TDE_FULL_SESSION") != NULL)
return "Trinity";
if(
getenv("WAYLAND_DISPLAY") != NULL &&
ffFileExists("/mnt/wslg/", S_IFDIR)
) return "WSLg";
return NULL;
}
static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* processName)
{
if(!ffStrSet(processName))
return;
if(
strcasecmp(processName, "kwin_wayland") == 0 ||
strcasecmp(processName, "kwin_wayland_wrapper") == 0 ||
strcasecmp(processName, "kwin_x11") == 0 ||
strcasecmp(processName, "kwin_x11_wrapper") == 0 ||
strcasecmp(processName, "kwin") == 0
) ffStrbufSetS(&result->wmPrettyName, "KWin");
else if(
strcasecmp(processName, "gnome-shell") == 0 ||
strcasecmp(processName, "gnome shell") == 0 ||
strcasecmp(processName, "gnome-session-binary") == 0 ||
strcasecmp(processName, "Mutter") == 0
) ffStrbufSetS(&result->wmPrettyName, "Mutter");
else if(
strcasecmp(processName, "cinnamon-session") == 0 ||
strcasecmp(processName, "Muffin") == 0
) ffStrbufSetS(&result->wmPrettyName, "Muffin");
else if(strcasecmp(processName, "sway") == 0)
ffStrbufSetS(&result->wmPrettyName, "Sway");
else if(strcasecmp(processName, "weston") == 0)
ffStrbufSetS(&result->wmPrettyName, "Weston");
else if(strcasecmp(processName, "wayfire") == 0)
ffStrbufSetS(&result->wmPrettyName, "Wayfire");
else if(strcasecmp(processName, "openbox") == 0)
ffStrbufSetS(&result->wmPrettyName, "Openbox");
else if(strcasecmp(processName, "xfwm4") == 0)
ffStrbufSetS(&result->wmPrettyName, "Xfwm4");
else if(strcasecmp(processName, "Marco") == 0)
ffStrbufSetS(&result->wmPrettyName, "Marco");
else if(strcasecmp(processName, "xmonad") == 0)
ffStrbufSetS(&result->wmPrettyName, "XMonad");
else if( // WMs where the pretty name matches the process name
strcasecmp(processName, "dwm") == 0 ||
strcasecmp(processName, "bspwm") == 0 ||
strcasecmp(processName, "tinywm") == 0
) ffStrbufSetS(&result->wmPrettyName, processName);
if(result->wmPrettyName.length > 0 && result->wmProcessName.length == 0)
ffStrbufSetS(&result->wmProcessName, processName);
}
static void applyBetterWM(FFDisplayServerResult* result, const char* processName)
{
if(!ffStrSet(processName))
return;
//If it is a known wm, this will set the pretty name
applyPrettyNameIfWM(result, processName);
//If it isn't a known wm, we have to set the process name our self
ffStrbufSetS(&result->wmProcessName, processName);
//If it isn't a known wm, set the pretty name to the process name
if(result->wmPrettyName.length == 0)
ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName);
}
static void getKDE(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "plasmashell");
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
applyBetterWM(result, getenv("KDEWM"));
}
static void getGnome(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "gnome-shell");
ffStrbufSetS(&result->dePrettyName, "GNOME");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
}
static void getCinnamon(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "cinnamon");
ffStrbufSetS(&result->dePrettyName, "Cinnamon");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
}
static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "mate-session");
ffStrbufSetS(&result->dePrettyName, "MATE");
FFstrbuf major;
ffStrbufInit(&major);
FFstrbuf minor;
ffStrbufInit(&minor);
FFstrbuf micro;
ffStrbufInit(&micro);
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR"/share/mate-about/mate-version.xml", 3, (FFpropquery[]) {
{"<platform>", &major},
{"<minor>", &minor},
{"<micro>", &micro}
});
ffParseSemver(&result->deVersion, &major, &minor, &micro);
ffStrbufDestroy(&major);
ffStrbufDestroy(&minor);
ffStrbufDestroy(&micro);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"mate-session",
"--version",
NULL
});
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
ffStrbufTrim(&result->deVersion, ' ');
}
}
static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "xfce4-session");
ffStrbufSetS(&result->dePrettyName, "Xfce4");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
//This is somewhat slow
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"xfce4-session",
"--version",
NULL
});
ffStrbufSubstrBeforeFirstC(&result->deVersion, '(');
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
ffStrbufTrim(&result->deVersion, ' ');
}
}
static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, "LXQt");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
//This is really, really, really slow. Thank you, LXQt developers
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"lxqt-session",
"-v",
NULL
});
result->deVersion.length = 0; //don't set '\0' byte
ffParsePropLines(result->deVersion.chars , "liblxqt", &result->deVersion);
}
FFstrbuf wmProcessNameBuffer;
ffStrbufInit(&wmProcessNameBuffer);
ffParsePropFileConfig(instance, "lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
applyBetterWM(result, wmProcessNameBuffer.chars);
ffStrbufDestroy(&wmProcessNameBuffer);
}
static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
return;
else if(
strcasecmp(name, "KDE") == 0 ||
strcasecmp(name, "plasma") == 0 ||
strcasecmp(name, "plasmashell") == 0 ||
strcasecmp(name, "plasmawayland") == 0
) getKDE(result);
else if(
strcasecmp(name, "Gnome") == 0 ||
strcasecmp(name, "ubuntu:GNOME") == 0 ||
strcasecmp(name, "ubuntu") == 0 ||
strcasecmp(name, "gnome-shell") == 0
) getGnome(result);
else if(
strcasecmp(name, "X-Cinnamon") == 0 ||
strcasecmp(name, "Cinnamon") == 0
) getCinnamon(result);
else if(
strcasecmp(name, "XFCE") == 0 ||
strcasecmp(name, "X-XFCE") == 0 ||
strcasecmp(name, "XFCE4") == 0 ||
strcasecmp(name, "X-XFCE4") == 0 ||
strcasecmp(name, "xfce4-session") == 0
) getXFCE4(instance, result);
else if(
strcasecmp(name, "MATE") == 0 ||
strcasecmp(name, "X-MATE") == 0 ||
strcasecmp(name, "mate-session") == 0
) getMate(instance, result);
else if(
strcasecmp(name, "LXQt") == 0 ||
strcasecmp(name, "X-LXQT") == 0 ||
strcasecmp(name, "lxqt-session") == 0
) getLXQt(instance, result);
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
{
//This is only called if all connection attempts to a display server failed
//We don't need to check for wayland here, as the wayland code will always set the protocol name to wayland
const char* env = getenv("XDG_SESSION_TYPE");
if(ffStrSet(env))
{
if(strcasecmp(env, "x11") == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
else if(strcasecmp(env, "tty") == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
else
ffStrbufSetS(&result->wmProtocolName, env);
return;
}
env = getenv("DISPLAY");
if(ffStrSet(env))
{
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
return;
}
env = getenv("TERM");
if(ffStrSet(env))
{
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
return;
}
}
static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* result)
{
DIR* proc = opendir("/proc");
if(proc == NULL)
return;
FFstrbuf procPath;
ffStrbufInitA(&procPath, 64);
ffStrbufAppendS(&procPath, "/proc/");
uint32_t procPathLength = procPath.length;
FFstrbuf userID;
ffStrbufInit(&userID);
ffStrbufAppendF(&userID, "%i", getuid());
FFstrbuf loginuid;
ffStrbufInit(&loginuid);
FFstrbuf processName;
ffStrbufInitA(&processName, 256); //Some processes have large command lines (looking at you chrome)
struct dirent* dirent;
while((dirent = readdir(proc)) != NULL)
{
//Match only folders starting with a number (the pid folders)
if(dirent->d_type != DT_DIR || !isdigit(dirent->d_name[0]))
continue;
ffStrbufAppendS(&procPath, dirent->d_name);
uint32_t procFolderPathLength = procPath.length;
//Don't check for processes not owend by the current user.
ffStrbufAppendS(&procPath, "/loginuid");
ffReadFileBuffer(procPath.chars, &loginuid);
if(ffStrbufComp(&userID, &loginuid) != 0)
{
ffStrbufSubstrBefore(&procPath, procPathLength);
continue;
}
ffStrbufSubstrBefore(&procPath, procFolderPathLength);
//We check the cmdline for the process name, because it is not trimmed.
ffStrbufAppendS(&procPath, "/cmdline");
ffReadFileBuffer(procPath.chars, &processName);
ffStrbufSubstrBeforeFirstC(&processName, '\0'); //Trim the arguments
ffStrbufSubstrAfterLastC(&processName, '/');
ffStrbufSubstrBefore(&procPath, procPathLength);
if(result->dePrettyName.length == 0)
applyPrettyNameIfDE(instance, result, processName.chars);
if(result->wmPrettyName.length == 0)
applyPrettyNameIfWM(result, processName.chars);
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
break;
}
closedir(proc);
ffStrbufDestroy(&processName);
ffStrbufDestroy(&loginuid);
ffStrbufDestroy(&userID);
ffStrbufDestroy(&procPath);
}
void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result)
{
//If all connections failed, use the environment variables to detect protocol name
if(result->wmProtocolName.length == 0)
getWMProtocolNameFromEnv(result);
//We don't want to detect anything in TTY
//This can't happen if a connection succeeded, so we don't need to clear wmProcessName
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY) == 0)
return;
const char* env = parseEnv();
if(result->wmProcessName.length > 0)
{
//If we found the processName via display server, use it.
//This will set the pretty name if it is a known WM, otherwise the prettyName to the processName
applyPrettyNameIfWM(result, result->wmProcessName.chars);
if(result->wmPrettyName.length == 0)
ffStrbufSet(&result->wmPrettyName, &result->wmProcessName);
}
else
{
//if env is a known WM, use it
applyPrettyNameIfWM(result, env);
}
//Connecting to a display server only gives WM results, not DE results.
//If we find it in the environment, use that.
applyPrettyNameIfDE(instance, result, env);
//If WM was found by connection to the sever, and DE in the environment, we can return
//This way we never call getFromProcDir(), which has slow initalization time
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
return;
//Get missing WM / DE from processes.
getFromProcDir(instance, result);
//Return if both wm and de are set, or if env doesn't contain anything
if(
(result->wmPrettyName.length > 0 && result->dePrettyName.length > 0) ||
!ffStrSet(env)
) return;
//If nothing is set, use env as WM
else if(result->wmPrettyName.length == 0 && result->dePrettyName.length == 0)
{
ffStrbufSetS(&result->wmProcessName, env);
ffStrbufSetS(&result->wmPrettyName, env);
}
//If only WM is not set, and DE doesn't equal env, use env as WM
else if(
result->wmPrettyName.length == 0 &&
ffStrbufIgnCaseCompS(&result->deProcessName, env) != 0 &&
ffStrbufIgnCaseCompS(&result->dePrettyName, env) != 0
) {
ffStrbufSetS(&result->wmProcessName, env);
ffStrbufSetS(&result->wmPrettyName, env);
}
//If only DE is not set, and WM doesn't equal env, use env as DE
else if(
result->dePrettyName.length == 0 &&
ffStrbufIgnCaseCompS(&result->wmProcessName, env) != 0 &&
ffStrbufIgnCaseCompS(&result->wmPrettyName, env) != 0
) {
ffStrbufSetS(&result->deProcessName, env);
ffStrbufSetS(&result->dePrettyName, env);
}
}
+395
View File
@@ -0,0 +1,395 @@
#include "displayserver_linux.h"
#ifdef FF_HAVE_XCB
#include "common/library.h"
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
typedef struct XcbPropertyData
{
FF_LIBRARY_SYMBOL(xcb_intern_atom)
FF_LIBRARY_SYMBOL(xcb_intern_atom_reply)
FF_LIBRARY_SYMBOL(xcb_get_property)
FF_LIBRARY_SYMBOL(xcb_get_property_reply)
FF_LIBRARY_SYMBOL(xcb_get_property_value)
FF_LIBRARY_SYMBOL(xcb_get_property_value_length)
} XcbPropertyData;
static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyData)
{
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_intern_atom, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_intern_atom_reply, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property_reply, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property_value, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property_value_length, false)
return true;
}
static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t window, const char* request)
{
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(connection, true, (uint16_t) strlen(request), request);
xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(connection, requestAtomCookie, NULL);
if(requestAtomReply == NULL)
return NULL;
xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 64);
free(requestAtomReply);
xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(connection, propertyCookie, NULL);
if(propertyReply == NULL)
return NULL;
int length = data->ffxcb_get_property_value_length(propertyReply);
if(length <= 0)
{
free(propertyReply);
return NULL;
}
//Why are xcb property strings not null terminated???
void* replyValue = malloc((size_t) (length + 1));
memcpy(replyValue, data->ffxcb_get_property_value(propertyReply), (size_t) length);
((char*) replyValue)[length] = '\0';
free(propertyReply);
return replyValue;
}
static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0)
return;
xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK");
if(wmWindow == NULL)
return;
char* wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "_NET_WM_NAME");
if(wmName == NULL)
wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "WM_NAME");
free(wmWindow);
if(wmName == NULL)
return;
if(*wmName == '\0')
{
free(wmName);
return;
}
ffStrbufSetS(&result->wmProcessName, wmName);
free(wmName);
}
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcb, instance->config.libXcb, , "libxcb.so", 2)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_connect,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_get_setup,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_setup_roots_iterator,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_screen_next,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_disconnect,)
XcbPropertyData propertyData;
bool propertyDataInitialized = xcbInitPropertyData(xcb, &propertyData);
xcb_connection_t* connection = ffxcb_connect(NULL, NULL);
if(connection == NULL)
{
dlclose(xcb);
return;
}
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(connection));
if(iterator.rem > 0 && propertyDataInitialized)
xcbDetectWMfromEWMH(&propertyData, connection, iterator.data->root, result);
while(iterator.rem > 0)
{
ffdsAppendResolution(
result,
(uint32_t) iterator.data->width_in_pixels,
(uint32_t) iterator.data->height_in_pixels,
0
);
ffxcb_screen_next(&iterator);
}
ffxcb_disconnect(connection);
dlclose(xcb);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
}
#else
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
{
//Do nothing. There are other implementations coming
FF_UNUSED(instance, result)
}
#endif
#ifdef FF_HAVE_XCB_RANDR
#include <xcb/randr.h>
typedef struct XcbRandrData
{
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources)
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_reply)
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_modes_iterator)
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_info)
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_info_reply)
FF_LIBRARY_SYMBOL(xcb_randr_mode_info_next)
FF_LIBRARY_SYMBOL(xcb_randr_get_monitors)
FF_LIBRARY_SYMBOL(xcb_randr_get_monitors_reply)
FF_LIBRARY_SYMBOL(xcb_randr_get_monitors_monitors_iterator)
FF_LIBRARY_SYMBOL(xcb_randr_monitor_info_next)
FF_LIBRARY_SYMBOL(xcb_randr_monitor_info_outputs_length)
FF_LIBRARY_SYMBOL(xcb_randr_monitor_info_outputs)
FF_LIBRARY_SYMBOL(xcb_randr_output_next)
FF_LIBRARY_SYMBOL(xcb_randr_get_output_info)
FF_LIBRARY_SYMBOL(xcb_randr_get_output_info_reply)
FF_LIBRARY_SYMBOL(xcb_randr_get_crtc_info)
FF_LIBRARY_SYMBOL(xcb_randr_get_crtc_info_reply)
//init once
xcb_connection_t* connection;
FFDisplayServerResult* result;
//init per screen
uint32_t defaultRefreshRate;
xcb_randr_get_screen_resources_reply_t* screenResources;
} XcbRandrData;
static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo)
{
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
modeInfo->dot_clock / (uint32_t) (modeInfo->htotal * modeInfo->vtotal)
));
return ffdsAppendResolution(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate == 0 ? data->defaultRefreshRate : refreshRate
);
}
static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode)
{
//We do the check here, because we want the best fallback resolution if this call failed
if(data->screenResources == NULL)
return false;
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_modes_iterator(data->screenResources);
while(modesIterator.rem > 0)
{
if(modesIterator.data->id == mode)
return xcbRandrHandleModeInfo(data, modesIterator.data);
data->ffxcb_randr_mode_info_next(&modesIterator);
}
return false;
}
static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
{
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME);
xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
if(crtcInfoReply == NULL)
return false;
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
res = res ? true : ffdsAppendResolution(
data->result,
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
data->defaultRefreshRate
);
free(crtcInfoReply);
return res;
}
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output)
{
xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME);
xcb_randr_get_output_info_reply_t* outputInfoReply = data->ffxcb_randr_get_output_info_reply(data->connection, outputInfoCookie, NULL);
if(outputInfoReply == NULL)
return false;
bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc);
free(outputInfoReply);
return res;
}
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor)
{
//for some reasons, we have to construct this our self
xcb_randr_output_iterator_t outputIterator = {
.index = 0,
.data = data->ffxcb_randr_monitor_info_outputs(monitor),
.rem = data->ffxcb_randr_monitor_info_outputs_length(monitor)
};
bool foundOutput = false;
while(outputIterator.rem > 0)
{
if(xcbRandrHandleOutput(data, *outputIterator.data))
foundOutput = true;
data->ffxcb_randr_output_next(&outputIterator);
};
return foundOutput ? true : ffdsAppendResolution(
data->result,
(uint32_t) monitor->width,
(uint32_t) monitor->height,
data->defaultRefreshRate
);
}
static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
{
xcb_randr_get_monitors_cookie_t monitorsCookie = data->ffxcb_randr_get_monitors(data->connection, screen->root, true);
xcb_randr_get_monitors_reply_t* monitorsReply = data->ffxcb_randr_get_monitors_reply(data->connection, monitorsCookie, NULL);
if(monitorsReply == NULL)
return false;
xcb_randr_monitor_info_iterator_t monitorInfoIterator = data->ffxcb_randr_get_monitors_monitors_iterator(monitorsReply);
bool foundMonitor = false;
while(monitorInfoIterator.rem > 0)
{
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data))
foundMonitor = true;
data->ffxcb_randr_monitor_info_next(&monitorInfoIterator);
}
free(monitorsReply);
return foundMonitor;
}
static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
{
//Init screen info. This is used to get the default refresh rate. If this fails, default refresh rate is simply 0.
xcb_randr_get_screen_info_cookie_t screenInfoCookie = data->ffxcb_randr_get_screen_info(data->connection, screen->root);
xcb_randr_get_screen_info_reply_t* screenInfoReply = data->ffxcb_randr_get_screen_info_reply(data->connection, screenInfoCookie, NULL);
if(screenInfoReply != NULL)
{
data->defaultRefreshRate = screenInfoReply->rate;
free(screenInfoReply);
}
else
data->defaultRefreshRate = 0;
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
xcb_randr_get_screen_resources_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources(data->connection, screen->root);
data->screenResources = data->ffxcb_randr_get_screen_resources_reply(data->connection, screenResourcesCookie, NULL);
//With all the initialisation done, start the detection
bool ret = xcbRandrHandleMonitors(data, screen);
free(data->screenResources);
if(ret)
return;
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
ffdsAppendResolution(
data->result,
(uint32_t) screen->width_in_pixels,
(uint32_t) screen->height_in_pixels,
data->defaultRefreshRate
);
}
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcbRandr, instance->config.libXcbRandr, , "libxcb-randr.so", 1)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_connect,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_get_setup,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_setup_roots_iterator,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_screen_next,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_disconnect,)
XcbRandrData data;
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_screen_resources,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_screen_resources_reply,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_screen_resources_modes_iterator,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_screen_info,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_screen_info_reply,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_mode_info_next,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_monitors,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_monitors_reply,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_monitors_monitors_iterator,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_monitor_info_next,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_monitor_info_outputs_length,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_monitor_info_outputs,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_output_next,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_output_info,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_output_info_reply,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_crtc_info,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_crtc_info_reply,)
XcbPropertyData propertyData;
bool propertyDataInitialized = xcbInitPropertyData(xcbRandr, &propertyData);
data.connection = ffxcb_connect(NULL, NULL);
if(data.connection == NULL)
{
dlclose(xcbRandr);
return;
}
data.result = result;
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(data.connection));
if(iterator.rem > 0 && propertyDataInitialized)
xcbDetectWMfromEWMH(&propertyData, data.connection, iterator.data->root, result);
while(iterator.rem > 0)
{
xcbRandrHandleScreen(&data, iterator.data);
ffxcb_screen_next(&iterator);
}
ffxcb_disconnect(data.connection);
dlclose(xcbRandr);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
}
#else
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result)
{
//Do nothing. There are other implementations coming
FF_UNUSED(instance, result)
}
#endif
+315
View File
@@ -0,0 +1,315 @@
#include "displayserver_linux.h"
#ifdef FF_HAVE_X11
#include "common/library.h"
#include "common/parsing.h"
#include <X11/Xlib.h>
typedef struct X11PropertyData
{
FF_LIBRARY_SYMBOL(XInternAtom)
FF_LIBRARY_SYMBOL(XGetWindowProperty)
} X11PropertyData;
static bool x11InitPropertyData(void* libraryHandle, X11PropertyData* propertyData)
{
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XInternAtom, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XGetWindowProperty, false)
return true;
}
static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Window window, const char* request)
{
Atom requestAtom = data->ffXInternAtom(display, request, False);
if(requestAtom == None)
return NULL;
Atom actualType;
unsigned long unused;
unsigned char* result = NULL;
data->ffXGetWindowProperty(display, window, requestAtom, 0, 64, False, AnyPropertyType, &actualType, (int*) &unused, &unused, &unused, &result);
return result;
}
static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0)
return;
Window* wmWindow = (Window*) x11GetProperty(data, display, DefaultRootWindow(display), "_NET_SUPPORTING_WM_CHECK");
if(wmWindow == NULL)
return;
const char* wmName = (const char*) x11GetProperty(data, display, *wmWindow, "_NET_WM_NAME");
if(wmName == NULL)
wmName = (const char*) x11GetProperty(data, display, *wmWindow, "WM_NAME");
if(!ffStrSet(wmName))
return;
ffStrbufSetS(&result->wmProcessName, wmName);
}
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(x11, instance->config.libX11, , "libX11.so", 7, "libX11-xcb.so", 2)
FF_LIBRARY_LOAD_SYMBOL(x11, XOpenDisplay,)
FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay,)
X11PropertyData propertyData;
bool propertyDataInitialized = x11InitPropertyData(x11, &propertyData);
Display* display = ffXOpenDisplay(x11);
if(display == NULL)
{
dlclose(x11);
return;
}
if(propertyDataInitialized && ScreenCount(display) > 0)
x11DetectWMFromEWMH(&propertyData, display, result);
for(int i = 0; i < ScreenCount(display); i++)
{
Screen* screen = ScreenOfDisplay(display, i);
ffdsAppendResolution(
result,
(uint32_t) screen->width,
(uint32_t) screen->height,
0
);
}
ffXCloseDisplay(display);
dlclose(x11);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
}
#else
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
{
//Do nothing. WM / DE detection will use environment vars to detect as much as possible.
FF_UNUSED(instance, result);
}
#endif //FF_HAVE_X11
#ifdef FF_HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
typedef struct XrandrData
{
FF_LIBRARY_SYMBOL(XRRGetScreenInfo)
FF_LIBRARY_SYMBOL(XRRConfigCurrentConfiguration)
FF_LIBRARY_SYMBOL(XRRConfigCurrentRate)
FF_LIBRARY_SYMBOL(XRRGetMonitors)
FF_LIBRARY_SYMBOL(XRRGetScreenResources)
FF_LIBRARY_SYMBOL(XRRGetOutputInfo)
FF_LIBRARY_SYMBOL(XRRGetCrtcInfo)
FF_LIBRARY_SYMBOL(XRRFreeCrtcInfo)
FF_LIBRARY_SYMBOL(XRRFreeOutputInfo)
FF_LIBRARY_SYMBOL(XRRFreeScreenResources)
FF_LIBRARY_SYMBOL(XRRFreeMonitors)
FF_LIBRARY_SYMBOL(XRRFreeScreenConfigInfo)
//Init once
Display* display;
FFDisplayServerResult* result;
//Init per screen
uint32_t defaultRefreshRate;
XRRScreenResources* screenResources;
} XrandrData;
static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
{
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)
));
return ffdsAppendResolution(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate == 0 ? data->defaultRefreshRate : refreshRate
);
}
static bool xrandrHandleMode(XrandrData* data, RRMode mode)
{
for(int i = 0; i < data->screenResources->nmode; i++)
{
if(data->screenResources->modes[i].id == mode)
return xrandrHandleModeInfo(data, &data->screenResources->modes[i]);
}
return false;
}
static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
{
//We do the check here, because we want the best fallback resolution if this call failed
if(data->screenResources == NULL)
return false;
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, crtc);
if(crtcInfo == NULL)
return false;
bool res = xrandrHandleMode(data, crtcInfo->mode);
res = res ? true : ffdsAppendResolution(
data->result,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
data->defaultRefreshRate
);
data->ffXRRFreeCrtcInfo(crtcInfo);
return res;
}
static bool xrandrHandleOutput(XrandrData* data, RROutput output)
{
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output);
if(outputInfo == NULL)
return false;
bool res = xrandrHandleCrtc(data, outputInfo->crtc);
data->ffXRRFreeOutputInfo(outputInfo);
return res;
}
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
{
bool foundOutput = false;
for(int i = 0; i < monitorInfo->noutput; i++)
{
if(xrandrHandleOutput(data, monitorInfo->outputs[i]))
foundOutput = true;
}
return foundOutput ? true : ffdsAppendResolution(
data->result,
(uint32_t) monitorInfo->width,
(uint32_t) monitorInfo->height,
data->defaultRefreshRate
);
}
static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
{
int numberOfMonitors;
XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, RootWindowOfScreen(screen), True, &numberOfMonitors);
if(monitorInfos == NULL)
return false;
bool foundAMonitor;
for(int i = 0; i < numberOfMonitors; i++)
{
if(xrandrHandleMonitor(data, &monitorInfos[i]))
foundAMonitor = true;
}
data->ffXRRFreeMonitors(monitorInfos);
return foundAMonitor;
}
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
{
//Init screen configuration. This is used to get the default refresh rate. If this fails, default refresh rate is simply 0.
XRRScreenConfiguration* screenConfiguration = data->ffXRRGetScreenInfo(data->display, RootWindowOfScreen(screen));
if(screenConfiguration != NULL)
{
data->defaultRefreshRate = (uint32_t) data->ffXRRConfigCurrentRate(screenConfiguration);
data->ffXRRFreeScreenConfigInfo(screenConfiguration);
}
else
data->defaultRefreshRate = 0;
//Init screen resources
data->screenResources = data->ffXRRGetScreenResources(data->display, RootWindowOfScreen(screen));
bool ret = xrandrHandleMonitors(data, screen);
data->ffXRRFreeScreenResources(data->screenResources);
if(ret)
return;
//Fallback to screen
ffdsAppendResolution(
data->result,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
data->defaultRefreshRate
);
}
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xrandr, instance->config.libXrandr, , "libXrandr.so", 3)
FF_LIBRARY_LOAD_SYMBOL(xrandr, XOpenDisplay,)
FF_LIBRARY_LOAD_SYMBOL(xrandr, XCloseDisplay,)
XrandrData data;
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetScreenInfo,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRConfigCurrentRate,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetMonitors,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetScreenResources,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetOutputInfo,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetCrtcInfo,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRFreeCrtcInfo,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRFreeOutputInfo,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRFreeScreenResources,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRFreeMonitors,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRFreeScreenConfigInfo,);
X11PropertyData propertyData;
bool propertyDataInitialized = x11InitPropertyData(xrandr, &propertyData);
data.display = ffXOpenDisplay(NULL);
if(data.display == NULL)
{
dlclose(xrandr);
return;
}
if(propertyDataInitialized && ScreenCount(data.display) > 0)
x11DetectWMFromEWMH(&propertyData, data.display, result);
data.result = result;
for(int i = 0; i < ScreenCount(data.display); i++)
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
ffXCloseDisplay(data.display);
dlclose(xrandr);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
}
#else
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result)
{
//Do nothing here. There are more x11 implementaions to come.
FF_UNUSED(instance, result);
}
#endif // FF_HAVE_XRANDR
+19
View File
@@ -0,0 +1,19 @@
#include "gpu.h"
#include "detection/internal.h"
#include "detection/vulkan.h"
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
const FFlist* ffDetectGPU(const FFinstance* instance)
{
FF_DETECTION_INTERNAL_GUARD(FFlist,
ffListInit(&result, sizeof(FFGPUResult));
ffDetectGPUImpl(&result, instance);
if(result.length == 0)
{
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
result = vulkan->gpus;
}
);
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#ifndef FF_INCLUDED_detection_gpu_gpu
#define FF_INCLUDED_detection_gpu_gpu
#include "fastfetch.h"
#define FF_GPU_TEMP_UNSET (0/0.0)
typedef struct FFGPUResult
{
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
double temperature;
} FFGPUResult;
const FFlist* ffDetectGPU(const FFinstance* instance);
#endif
+6
View File
@@ -0,0 +1,6 @@
#include "gpu.h"
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
FF_UNUSED(gpus, instance);
}
+68
View File
@@ -0,0 +1,68 @@
#include "gpu.h"
#include "common/library.h"
#include "detection/cpu/cpu.h"
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/graphics/IOGraphicsLib.h>
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
FF_UNUSED(instance);
const FFCPUResult* cpu = ffDetectCPU();
if(ffStrbufStartsWithIgnCaseS(&cpu->name, "Apple M"))
{
FFGPUResult* gpu = ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
ffStrbufAppendS(&gpu->vendor, "Apple");
ffStrbufInit(&gpu->name);
ffStrbufAppendS(&gpu->name, cpu->name.chars + 6); //Cut "Apple "
ffStrbufInitA(&gpu->driver, 0);
gpu->temperature = FF_GPU_TEMP_UNSET;
}
CFMutableDictionaryRef matchDict = IOServiceMatching("IOPCIDevice");
io_iterator_t iterator;
if(IOServiceGetMatchingServices(0, matchDict, &iterator) != kIOReturnSuccess)
return;
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
CFStringRef key = CFStringCreateWithCStringNoCopy(NULL, "model", kCFStringEncodingASCII, kCFAllocatorNull);
CFStringRef model = CFDictionaryGetValue(properties, key);
if(model == NULL || CFGetTypeID(model) != CFDataGetTypeID())
{
CFRelease(properties);
IOObjectRelease(registryEntry);
continue;
}
FFGPUResult* gpu = ffListAdd(gpus);
uint32_t modelLength = (uint32_t) CFStringGetLength(model);
ffStrbufInitA(&gpu->name, modelLength + 1);
CFStringGetCString(model, gpu->name.chars, modelLength + 1, kCFStringEncodingASCII);
gpu->name.length = modelLength;
gpu->name.chars[gpu->name.length] = '\0';
ffStrbufInitA(&gpu->vendor, 0);
ffStrbufInitA(&gpu->driver, 0);
gpu->temperature = FF_GPU_TEMP_UNSET;
CFRelease(properties);
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
}
+212
View File
@@ -0,0 +1,212 @@
#include "gpu.h"
#include "detection/vulkan.h"
#define FF_GPU_VENDOR_NAME_AMD "AMD"
#define FF_GPU_VENDOR_NAME_INTEL "Intel"
#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA"
#ifdef FF_HAVE_LIBPCI
#include "common/library.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "detection/temps.h"
#include <string.h>
#include <unistd.h>
#include <pci/pci.h>
typedef struct PCIData
{
struct pci_access* access;
FF_LIBRARY_SYMBOL(pci_read_byte);
FF_LIBRARY_SYMBOL(pci_read_word);
FF_LIBRARY_SYMBOL(pci_lookup_name);
FF_LIBRARY_SYMBOL(pci_get_param);
} PCIData;
static bool pciIDsContains(u16 searched, const u16* ids)
{
while(*ids != 0)
{
if(*ids == searched)
return true;
ids++;
}
return false;
}
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(pciIDsContains(device->vendor_id, (const u16[]) {0x1002, 0x1022, 0}))
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x03e7, 0x8086, 0x8087, 0}))
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x0955, 0x10de, 0x12d2, 0}))
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
if(gpu->vendor.length > 0)
return;
ffStrbufEnsureFree(&gpu->vendor, 255);
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id);
ffStrbufRecalculateLength(&gpu->vendor);
if(ffStrbufFirstIndexS(&gpu->vendor, "AMD") < gpu->vendor.length || ffStrbufFirstIndexS(&gpu->vendor, "ATI") < gpu->vendor.length)
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(ffStrbufFirstIndexS(&gpu->vendor, "Intel") < gpu->vendor.length)
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(ffStrbufFirstIndexS(&gpu->vendor, "NVIDIA") < gpu->vendor.length)
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
}
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
FFstrbuf query;
ffStrbufInit(&query);
ffStrbufAppendF(&query, "%X, %X,", device->device_id, pci->ffpci_read_byte(device, PCI_REVISION_ID));
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->name);
ffStrbufDestroy(&query);
const char* removeStrings[] = {
"AMD ", "ATI ",
" (TM)", "(TM)",
" Graphics Adapter", " Graphics", " Series", " Edition"
};
ffStrbufRemoveStringsA(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
}
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(ffStrbufCompS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD) == 0)
{
drmDetectDeviceName(gpu, pci, device);
if(gpu->name.length > 0)
return;
}
ffStrbufEnsureFree(&gpu->name, 255);
pci->ffpci_lookup_name(pci->access, gpu->name.chars, (int) gpu->name.allocated, PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
ffStrbufRecalculateLength(&gpu->name);
uint32_t openingBracket = ffStrbufFirstIndexC(&gpu->name, '[');
uint32_t closingBracket = ffStrbufNextIndexC(&gpu->name, openingBracket, ']');
if(closingBracket < gpu->name.length)
{
ffStrbufSubstrBefore(&gpu->name, closingBracket);
ffStrbufSubstrAfter(&gpu->name, openingBracket);
}
}
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
if(!ffStrSet(base))
return;
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
ffStrbufEnsureFree(&gpu->driver, 1023);
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
if(resultLength > 0)
{
gpu->driver.length = (uint32_t) resultLength;
gpu->driver.chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
}
ffStrbufDestroy(&path);
}
static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
{
const FFTempsResult* tempsResult = ffDetectTemps();
for(uint32_t i = 0; i < tempsResult->values.length; i++)
{
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
uint32_t tempClass;
if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1)
continue;
//The kernel exposes the device class multiplied by 256 for some reason
if(tempClass == device->device_class * 256)
{
gpu->temperature = tempValue->value;
return;
}
}
}
static void pciHandleDevice(FFlist* results, PCIData* pci, struct pci_dev* device)
{
device->device_class = pci->ffpci_read_word(device, PCI_CLASS_DEVICE);
char class[1024];
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
if(
strcasecmp("VGA compatible controller", class) != 0 &&
strcasecmp("3D controller", class) != 0 &&
strcasecmp("Display controller", class) != 0
) return;
device->vendor_id = pci->ffpci_read_word(device, PCI_VENDOR_ID);
device->device_id = pci->ffpci_read_word(device, PCI_DEVICE_ID);
FFGPUResult* gpu = ffListAdd(results);
ffStrbufInit(&gpu->vendor);
pciDetectVendorName(gpu, pci, device);
ffStrbufInit(&gpu->name);
pciDetectDeviceName(gpu, pci, device);
ffStrbufInit(&gpu->driver);
pciDetectDriverName(gpu, pci, device);
gpu->temperature = FF_GPU_TEMP_UNSET;
pciDetectTemperatur(gpu, device);
}
static void pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
{
PCIData pci;
FF_LIBRARY_LOAD(libpci, instance->config.libPCI, , "libpci.so", 4)
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_alloc, )
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_init, )
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_scan_bus, )
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_cleanup, )
FF_LIBRARY_LOAD_SYMBOL_VAR(libpci, pci, pci_read_byte, )
FF_LIBRARY_LOAD_SYMBOL_VAR(libpci, pci, pci_read_word, )
FF_LIBRARY_LOAD_SYMBOL_VAR(libpci, pci, pci_lookup_name, )
FF_LIBRARY_LOAD_SYMBOL_VAR(libpci, pci, pci_get_param, )
pci.access = ffpci_alloc();
ffpci_init(pci.access);
ffpci_scan_bus(pci.access);
struct pci_dev* device = pci.access->devices;
while(device != NULL)
{
pciHandleDevice(gpus, &pci, device);
device = device->next;
}
ffpci_cleanup(pci.access);
dlclose(libpci);
}
#endif
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
#ifdef FF_HAVE_LIBPCI
pciDetectGPUs(instance, gpus);
#endif
}
+204
View File
@@ -0,0 +1,204 @@
#include "fastfetch.h"
#include "detection/gtk.h"
#include "common/properties.h"
#include "common/settings.h"
#include "detection/displayserver/displayserver.h"
#include <pthread.h>
static inline bool allPropertiesSet(FFGTKResult* result)
{
return
result->theme.length > 0 &&
result->icons.length > 0 &&
result->font.length > 0;
}
static inline void applyGTKSettings(FFGTKResult* result, const char* themeName, const char* iconsName, const char* fontName, const char* cursorTheme, int cursorSize)
{
if(result->theme.length == 0)
ffStrbufAppendS(&result->theme, themeName);
if(result->icons.length == 0)
ffStrbufAppendS(&result->icons, iconsName);
if(result->font.length == 0)
ffStrbufAppendS(&result->font, fontName);
if(result->cursor.length == 0)
ffStrbufAppendS(&result->cursor, cursorTheme);
if(result->cursorSize.length == 0 && cursorSize > 0)
ffStrbufAppendF(&result->cursorSize, "%i", cursorSize);
}
static void detectGTKFromSettings(FFinstance* instance, FFGTKResult* result)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static const char* themeName = NULL;
static const char* iconsName = NULL;
static const char* fontName = NULL;
static const char* cursorTheme = NULL;
static int cursorSize = 0;
static bool init = false;
pthread_mutex_lock(&mutex);
if(init)
{
pthread_mutex_unlock(&mutex);
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
return;
}
init = true;
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Xfce") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Xfce4") == 0)
{
themeName = ffSettingsGetXFConf(instance, "xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue;
iconsName = ffSettingsGetXFConf(instance, "xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue;
fontName = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue;
cursorTheme = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue;
cursorSize = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
}
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0)
{
themeName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
iconsName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
fontName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
cursorTheme = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
cursorSize = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
}
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0)
{
themeName = ffSettingsGet(instance, "/org/mate/interface/gtk-theme", "org.mate.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
iconsName = ffSettingsGet(instance, "/org/mate/interface/icon-theme", "org.mate.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
fontName = ffSettingsGet(instance, "/org/mate/interface/font-name", "org.mate.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
cursorTheme = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
cursorSize = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
}
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0)
{
themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
cursorTheme = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
cursorSize = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
}
pthread_mutex_unlock(&mutex);
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
}
static void detectGTKFromConfigFile(const char* filename, FFGTKResult* result)
{
ffParsePropFileValues(filename, 5, (FFpropquery[]) {
{"gtk-theme-name =", &result->theme},
{"gtk-icon-theme-name =", &result->icons},
{"gtk-font-name =", &result->font},
{"gtk-cursor-theme-name =", &result->cursor},
{"gtk-cursor-theme-size =", &result->cursorSize}
});
}
static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFGTKResult* result)
{
uint32_t configDirLength = configDir->length;
// <configdir>/gtk-<version>.0/settings.ini
ffStrbufAppendS(configDir, "gtk-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0/settings.ini");
detectGTKFromConfigFile(configDir->chars, result);
ffStrbufSubstrBefore(configDir, configDirLength);
if(allPropertiesSet(result))
return;
// <configdir>/gtk-<version>.0/gtkrc
ffStrbufAppendS(configDir, "gtk-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0/gtkrc");
detectGTKFromConfigFile(configDir->chars, result);
ffStrbufSubstrBefore(configDir, configDirLength);
if(allPropertiesSet(result))
return;
// <configdir>/gtkrc-<version>.0
ffStrbufAppendS(configDir, "gtkrc-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0");
detectGTKFromConfigFile(configDir->chars, result);
ffStrbufSubstrBefore(configDir, configDirLength);
if(allPropertiesSet(result))
return;
// <configdir>/.gtkrc-<version>.0
ffStrbufAppendS(configDir, ".gtkrc-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0");
detectGTKFromConfigFile(configDir->chars, result);
ffStrbufSubstrBefore(configDir, configDirLength);
}
static void detectGTK(FFinstance* instance, const char* version, FFGTKResult* result)
{
//Mate, Cinnamon and Gnome use dconf to save theme config
//On other DEs, this will do nothing
detectGTKFromSettings(instance, result);
if(allPropertiesSet(result))
return;
//We need to do this because we use multiple threads on configDirs
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
{
ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
detectGTKFromConfigDir(&baseDir, version, result);
if(allPropertiesSet(result))
break;
}
ffStrbufDestroy(&baseDir);
}
#define FF_DETECT_GTK_IMPL(version) \
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
static FFGTKResult result; \
static bool init = false; \
pthread_mutex_lock(&mutex); \
if(init){ \
pthread_mutex_unlock(&mutex);\
return &result; \
} \
init = true; \
ffStrbufInit(&result.theme); \
ffStrbufInit(&result.icons); \
ffStrbufInit(&result.font); \
ffStrbufInit(&result.cursor); \
ffStrbufInit(&result.cursorSize); \
detectGTK(instance, #version, &result); \
pthread_mutex_unlock(&mutex); \
return &result;
const FFGTKResult* ffDetectGTK2(FFinstance* instance)
{
FF_DETECT_GTK_IMPL(2)
}
const FFGTKResult* ffDetectGTK3(FFinstance* instance)
{
FF_DETECT_GTK_IMPL(3)
}
const FFGTKResult* ffDetectGTK4(FFinstance* instance)
{
FF_DETECT_GTK_IMPL(4)
}
#undef FF_CALCULATE_GTK_IMPL
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#ifndef FF_INCLUDED_detection_gtk
#define FF_INCLUDED_detection_gtk
#include "fastfetch.h"
typedef struct FFGTKResult
{
FFstrbuf theme;
FFstrbuf icons;
FFstrbuf font;
FFstrbuf cursor;
FFstrbuf cursorSize;
} FFGTKResult;
const FFGTKResult* ffDetectGTK2(FFinstance* instance);
const FFGTKResult* ffDetectGTK4(FFinstance* instance);
const FFGTKResult* ffDetectGTK3(FFinstance* instance);
#endif
+11
View File
@@ -0,0 +1,11 @@
#include "host.h"
#include "detection/internal.h"
void ffDetectHostImpl(FFHostResult* host);
const FFHostResult* ffDetectHost()
{
FF_DETECTION_INTERNAL_GUARD(FFHostResult,
ffDetectHostImpl(&result)
);
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#ifndef FF_INCLUDED_detection_host_host
#define FF_INCLUDED_detection_host_host
#include "fastfetch.h"
#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux"
typedef struct FFHostResult
{
FFstrbuf productFamily;
FFstrbuf productName;
FFstrbuf productVersion;
FFstrbuf productSku;
FFstrbuf biosDate;
FFstrbuf biosRelease;
FFstrbuf biosVendor;
FFstrbuf biosVersion;
FFstrbuf boardName;
FFstrbuf boardVendor;
FFstrbuf boardVersion;
FFstrbuf chassisType;
FFstrbuf chassisVendor;
FFstrbuf chassisVersion;
FFstrbuf sysVendor;
} FFHostResult;
const FFHostResult* ffDetectHost();
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "host.h"
#include "common/settings.h"
#include <ctype.h>
void ffDetectHostImpl(FFHostResult* host)
{
//Family
ffStrbufInit(&host->productFamily);
ffSettingsGetAndroidProperty("ro.product.device", &host->productFamily);
//Name
ffStrbufInit(&host->productName);
ffSettingsGetAndroidProperty("ro.product.brand", &host->productName);
if(host->productName.length > 0){
host->productName.chars[0] = (char) toupper(host->productName.chars[0]);
ffStrbufAppendC(&host->productName, ' ');
}
ffSettingsGetAndroidProperty("ro.product.model", &host->productName);
ffStrbufTrimRight(&host->productName, ' ');
//Sys vendor
ffStrbufInit(&host->sysVendor);
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->sysVendor);
//Not implemented
ffStrbufInitA(&host->productVersion, 0);
ffStrbufInitA(&host->productSku, 0);
ffStrbufInitA(&host->biosDate, 0);
ffStrbufInitA(&host->biosRelease, 0);
ffStrbufInitA(&host->biosVendor, 0);
ffStrbufInitA(&host->biosVersion, 0);
ffStrbufInitA(&host->boardName, 0);
ffStrbufInitA(&host->boardVendor, 0);
ffStrbufInitA(&host->boardVersion, 0);
ffStrbufInitA(&host->chassisType, 0);
ffStrbufInitA(&host->chassisVendor, 0);
ffStrbufInitA(&host->chassisVersion, 0);
}
+24
View File
@@ -0,0 +1,24 @@
#include "host.h"
#include "common/settings.h"
void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->productName);
ffStrbufInitA(&host->productFamily, 0);
ffStrbufInitA(&host->sysVendor, 0);
ffStrbufInitA(&host->productVersion, 0);
ffStrbufInitA(&host->productSku, 0);
ffStrbufInitA(&host->biosDate, 0);
ffStrbufInitA(&host->biosRelease, 0);
ffStrbufInitA(&host->biosVendor, 0);
ffStrbufInitA(&host->biosVersion, 0);
ffStrbufInitA(&host->boardName, 0);
ffStrbufInitA(&host->boardVendor, 0);
ffStrbufInitA(&host->boardVersion, 0);
ffStrbufInitA(&host->chassisType, 0);
ffStrbufInitA(&host->chassisVendor, 0);
ffStrbufInitA(&host->chassisVersion, 0);
ffSettingsGetAppleProperty("hw.model", &host->productName);
}
+118
View File
@@ -0,0 +1,118 @@
#include "host.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);
}
static void getHostProductName(FFstrbuf* name)
{
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name);
if(name->length > 0)
return;
ffReadFileBuffer("/sys/firmware/devicetree/base/model", name);
if(hostValueSet(name))
return;
//does a clear before the read
ffReadFileBuffer("/tmp/sysinfo/model", name);
if(hostValueSet(name))
return;
ffStrbufClear(name);
}
void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->productFamily);
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
ffStrbufInit(&host->productName);
getHostProductName(&host->productName);
ffStrbufInit(&host->productVersion);
getHostValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion);
ffStrbufInit(&host->productSku);
getHostValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
ffStrbufInit(&host->biosDate);
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &host->biosDate);
ffStrbufInit(&host->biosRelease);
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &host->biosRelease);
ffStrbufInit(&host->biosVendor);
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &host->biosVendor);
ffStrbufInit(&host->biosVersion);
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &host->biosVersion);
ffStrbufInit(&host->boardName);
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &host->boardName);
ffStrbufInit(&host->boardVendor);
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &host->boardVendor);
ffStrbufInit(&host->boardVersion);
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &host->boardVersion);
ffStrbufInit(&host->chassisType);
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &host->chassisType);
ffStrbufInit(&host->chassisVendor);
getHostValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &host->chassisVendor);
ffStrbufInit(&host->chassisVersion);
getHostValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &host->chassisVersion);
ffStrbufInit(&host->sysVendor);
getHostValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor);
//KVM/Qemu virtual machine
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
//On WSL, the real host can't be detected. Instead use WSL as host.
if(host->productFamily.length == 0 && host->productName.length == 0 && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
)) ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#ifndef FF_INCLUDED_detection_internal
#define FF_INCLUDED_detection_internal
#include "pthread.h"
#define FF_DETECTION_INTERNAL_GUARD(ResultType, ...) \
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
static ResultType result; \
static bool init = false; \
pthread_mutex_lock(&mutex); \
if(init) \
{ \
pthread_mutex_unlock(&mutex); \
return &result; \
} \
init = true; \
__VA_ARGS__; \
pthread_mutex_unlock(&mutex); \
return &result; \
#endif
+369
View File
@@ -0,0 +1,369 @@
#include "fastfetch.h"
#include "detection/media.h"
#include <string.h>
#include <pthread.h>
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#ifdef FF_HAVE_DBUS
#include "common/library.h"
#include "common/parsing.h"
#include <dbus/dbus.h>
#define FF_DBUS_ITER_CONTINUE(iterator) \
{ \
if(!data->ffdbus_message_iter_has_next(&iterator)) \
break; \
data->ffdbus_message_iter_next(&iterator); \
continue; \
}
typedef struct DBusData
{
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
FF_LIBRARY_SYMBOL(dbus_message_iter_init)
FF_LIBRARY_SYMBOL(dbus_message_iter_init_append)
FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic)
FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type)
FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic)
FF_LIBRARY_SYMBOL(dbus_message_iter_recurse)
FF_LIBRARY_SYMBOL(dbus_message_iter_has_next)
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
FF_LIBRARY_SYMBOL(dbus_message_unref)
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply)
FF_LIBRARY_SYMBOL(dbus_connection_flush)
FF_LIBRARY_SYMBOL(dbus_pending_call_block)
FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply)
FF_LIBRARY_SYMBOL(dbus_pending_call_unref)
DBusConnection *connection;
} DBusData;
static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
{
int argType = data->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_STRING)
{
const char* value = NULL;
data->ffdbus_message_iter_get_basic(iter, &value);
if(!ffStrSet(value))
return false;
ffStrbufAppendS(result, value);
return true;
}
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
return false;
DBusMessageIter subIter;
data->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
return getValue(&subIter, result, data);
//At this point we have an array
bool foundAValue = false;
while(true)
{
if(getValue(&subIter, result, data))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(subIter);
}
if(foundAValue)
ffStrbufSubstrBefore(result, result->length - 2);
return foundAValue;
}
static DBusMessage* getReply(DBusMessage* request, DBusData* data)
{
DBusPendingCall* pendingCall = NULL;
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, FF_DBUS_TIMEOUT_MILLISECONDS);
data->ffdbus_message_unref(request);
if(!succesfull || pendingCall == NULL)
return NULL;
data->ffdbus_connection_flush(data->connection);
data->ffdbus_pending_call_block(pendingCall);
DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pendingCall);
data->ffdbus_pending_call_unref(pendingCall);
return reply;
}
static DBusMessage* getProperty(const char* busName, const char* objectPath, const char* interface, const char* property, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
if(message == NULL)
return NULL;
DBusMessageIter requestIterator;
data->ffdbus_message_iter_init_append(message, &requestIterator);
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
data->ffdbus_message_unref(message);
return NULL;
}
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
data->ffdbus_message_unref(message);
return NULL;
}
return getReply(message, data);
}
static void getPropertyString(const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, objectPath, interface, property, data);
if(reply == NULL)
return;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return;
}
getValue(&rootIterator, result, data);
data->ffdbus_message_unref(reply);
}
static bool getBusProperties(const char* busName, FFMediaResult* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata", data);
if(reply == NULL)
return false;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return false;
}
if(data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
{
data->ffdbus_message_unref(reply);
return false;
}
DBusMessageIter variantIterator;
data->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
if(data->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
{
data->ffdbus_message_unref(reply);
return false;
}
DBusMessageIter arrayIterator;
data->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
while(true)
{
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
FF_DBUS_ITER_CONTINUE(arrayIterator)
DBusMessageIter dictIterator;
data->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
if(data->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(!data->ffdbus_message_iter_has_next(&dictIterator))
FF_DBUS_ITER_CONTINUE(arrayIterator)
const char* key;
data->ffdbus_message_iter_get_basic(&dictIterator, &key);
data->ffdbus_message_iter_next(&dictIterator);
if(strcmp(key, "xesam:title") == 0)
getValue(&dictIterator, &result->song, data);
else if(strcmp(key, "xesam:album") == 0)
getValue(&dictIterator, &result->album, data);
else if(strcmp(key, "xesam:artist") == 0)
getValue(&dictIterator, &result->artist, data);
else if(strcmp(key, "xesam:url") == 0)
getValue(&dictIterator, &result->url, data);
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0)
break;
FF_DBUS_ITER_CONTINUE(arrayIterator)
}
data->ffdbus_message_unref(reply);
if(result->song.length == 0)
{
ffStrbufClear(&result->artist);
ffStrbufClear(&result->album);
ffStrbufClear(&result->url);
return false;
}
//Set short bus name
ffStrbufAppendS(&result->busNameShort, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
//We found a song, get the player name
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player, data);
if(result->player.length == 0)
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player, data);
if(result->player.length == 0)
ffStrbufAppend(&result->player, &result->busNameShort);
return true;
}
static void getCustomBus(FFinstance* instance, FFMediaResult* result, DBusData* data)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
{
getBusProperties(instance->config.playerName.chars, result, data);
return;
}
FFstrbuf busName;
ffStrbufInit(&busName);
ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX);
ffStrbufAppend(&busName, &instance->config.playerName);
getBusProperties(busName.chars, result, data);
ffStrbufDestroy(&busName);
}
static void getBestBus(FFMediaResult* result, DBusData* data)
{
if(
getBusProperties(FF_DBUS_MPRIS_PREFIX"spotify", result, data) ||
getBusProperties(FF_DBUS_MPRIS_PREFIX"vlc", result, data) ||
getBusProperties(FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result, data)
) return;
DBusMessage* message = data->ffdbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
if(message == NULL)
return;
DBusMessage* reply = getReply(message, data);
if(reply == NULL)
return;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator) || data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIterator;
data->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
while(true)
{
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(arrayIterator)
const char* busName;
data->ffdbus_message_iter_get_basic(&arrayIterator, &busName);
if(strncmp(busName, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(getBusProperties(busName, result, data))
break;
FF_DBUS_ITER_CONTINUE(arrayIterator)
}
data->ffdbus_message_unref(reply);
}
static void getMedia(FFinstance* instance, FFMediaResult* result)
{
DBusData data;
FF_LIBRARY_LOAD(dbus, instance->config.libDBus, , "libdbus-1.so", 4);
FF_LIBRARY_LOAD_SYMBOL(dbus, dbus_bus_get,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_new_method_call,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_init,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_init_append,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_append_basic,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_get_arg_type,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_get_basic,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_recurse,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_has_next,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_iter_next,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_message_unref,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_connection_send_with_reply,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_connection_flush,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_pending_call_block,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_pending_call_steal_reply,)
FF_LIBRARY_LOAD_SYMBOL_VAR(dbus, data, dbus_pending_call_unref,)
data.connection = ffdbus_bus_get(DBUS_BUS_SESSION, NULL);
if(data.connection == NULL)
{
dlclose(dbus);
return;
}
if(instance->config.playerName.length > 0)
getCustomBus(instance, result, &data);
else
getBestBus(result, &data);
dlclose(dbus);
}
#endif
const FFMediaResult* ffDetectMedia(FFinstance* instance)
{
static FFMediaResult result;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static bool init = false;
pthread_mutex_lock(&mutex);
if(init)
{
pthread_mutex_unlock(&mutex);
return &result;
}
init = true;
ffStrbufInit(&result.busNameShort);
ffStrbufInit(&result.player);
ffStrbufInit(&result.song);
ffStrbufInit(&result.artist);
ffStrbufInit(&result.album);
ffStrbufInit(&result.url);
#ifdef FF_HAVE_DBUS
getMedia(instance, &result);
#endif
//Set player if a custom player was given, but loading with dbus failed
if(instance->config.playerName.length > 0 && result.song.length == 0)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
ffStrbufAppendS(&result.player, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
else
ffStrbufAppend(&result.player, &instance->config.playerName);
}
pthread_mutex_unlock(&mutex);
return &result;
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#ifndef FF_INCLUDED_detection_media
#define FF_INCLUDED_detection_media
#include "fastfetch.h"
typedef struct FFMediaResult
{
FFstrbuf busNameShort; //e.g. plasma-browser-integration
FFstrbuf player; // e.g. Google Chrome
FFstrbuf song;
FFstrbuf artist;
FFstrbuf album;
FFstrbuf url;
} FFMediaResult;
const FFMediaResult* ffDetectMedia(FFinstance* instance);
#endif
+21
View File
@@ -0,0 +1,21 @@
#include "memory.h"
#include "detection/internal.h"
void ffDetectMemoryImpl(FFMemoryResult* memory);
static void calculatePercentage(FFMemoryStorage* storage)
{
if(storage->bytesTotal == 0)
storage->percentage = 0;
else
storage->percentage = (uint8_t) ((storage->bytesUsed / (long double) storage->bytesTotal) * 100.0);
}
const FFMemoryResult* ffDetectMemory()
{
FF_DETECTION_INTERNAL_GUARD(FFMemoryResult,
ffDetectMemoryImpl(&result);
calculatePercentage(&result.ram);
calculatePercentage(&result.swap);
);
}

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