Compare commits

..

399 Commits

Author SHA1 Message Date
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
169 changed files with 11009 additions and 5502 deletions
+13 -5
View File
@@ -7,6 +7,13 @@ 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
@@ -18,6 +25,9 @@ Output of `fastfetch --load-config devinfo`:
```
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
```
@@ -27,9 +37,7 @@ 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 to much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
Often helpful questions:
* Does the issue occur across multiple terminal emulators?
* Does the issue occur across multiple shells? (bash, zsh, fish, etc)
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
-->
+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.
```
-37
View File
@@ -1,37 +0,0 @@
name: manage pull requests
on: pull_request
jobs:
check:
name: manage pull request
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: checkout repository
uses: actions/checkout@v2
- 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 libxfconf-0-dev rpm librpm-dev libzstd-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
- name: configure project
run: cmake -DBUILD_TESTS=On .
- name: build project
run: cmake --build . -j$(nproc) --target package
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true
- name: run flashfetch
run: ./flashfetch
- name: run tests
run: ctest
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v1
+82 -20
View File
@@ -1,36 +1,40 @@
name: manage pushes
on:
push:
branches: [ master ]
- push
- pull_request
jobs:
manage:
name: manage push
linux:
name: Linux
runs-on: ubuntu-latest
permissions:
contents: write
security-events: write
outputs:
ffversion: ${{ steps.ffversion.outputs.ffversion }}
steps:
- name: checkout repository
uses: actions/checkout@v2
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 libxfconf-0-dev rpm librpm-dev libzstd-dev
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@v1
uses: github/codeql-action/init@v2
with:
languages: c
- name: configure project
# We reuse the build binary only for the releases.
# We set tweak version to off, because it is wrong, as git tag will happen after this step. Releases don't have a tweak, so this is ok.
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
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
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: ./flashfetch
@@ -38,12 +42,69 @@ jobs:
- name: run tests
run: ctest
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v1
- name: get fastfetch version
id: get_version_fastfetch
run: echo "::set-output name=release::$(./fastfetch --version-raw)"
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
@@ -52,9 +113,10 @@ jobs:
repository: ${{ github.repository }}
- name: create release
if: steps.get_version_fastfetch.outputs.release != steps.get_version_release.outputs.release
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ steps.get_version_fastfetch.outputs.release }}
tag: ${{ needs.linux.outputs.ffversion }}
commit: ${{ github.sha }}
artifacts: ./fastfetch-*.*
artifactErrorsFailBuild: true
artifacts: fastfetch-linux/*,fastfetch-macos/*
+1 -2
View File
@@ -2,8 +2,7 @@
**/.vscode/
**/.cache/
**/.kdev4/
**/.DS_Store
cscope.*
tags
fastfetch.kdev4
**/*.deb
packaging/deb/fastfetch
+110
View File
@@ -0,0 +1,110 @@
# 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
+287 -198
View File
@@ -1,30 +1,122 @@
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 1.2.2
VERSION 1.7.1
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
)
# This is set to off by github actions for release builds
OPTION(SET_TWEAK "Add tweak to project version" ON)
###################
# Target Platform #
###################
# Also create test executables
OPTION(BUILD_TESTS "Build tests" OFF)
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()
OPTION(ENABLE_LIBPCI "Enable libpci" ON)
OPTION(ENABLE_VULKAN "Enable vulkan" ON)
OPTION(ENABLE_WAYLAND "Enable wayland-client" ON)
OPTION(ENABLE_XCB_RANDR "Enable xcb-randr" ON)
OPTION(ENABLE_XCB "Enable xcb" ON)
OPTION(ENABLE_XRANDR "Enable xrandr" ON)
OPTION(ENABLE_X11 "Enable x11" ON)
OPTION(ENABLE_GIO "Enable gio-2.0" ON)
OPTION(ENABLE_DCONF "Enable dconf" ON)
OPTION(ENABLE_DBUS "Enable dbus-1" ON)
OPTION(ENABLE_XFCONF "Enable libxfconf-0" ON)
OPTION(ENABLE_RPM "Enable rpm" ON)
#####################
# 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 #
#################
# Track commits between version bumps for output in --version
if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git describe --tags
@@ -35,12 +127,9 @@ if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-Wl,-O3")
#############
# Text data #
#############
function(fastfetch_load_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
@@ -51,47 +140,59 @@ function(fastfetch_load_text FILENAME OUTVAR)
endfunction(fastfetch_load_text)
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
fastfetch_load_text(src/data/config.txt DATATEXT_CONFIG)
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)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
#######################
# libfastfetch target #
#######################
find_package(PkgConfig REQUIRED)
# Init CMake targets
add_library(libfastfetch STATIC
set(LIBFASTFETCH_SRC
src/util/FFstrbuf.c
src/util/FFlist.c
src/util/FFvaluestore.c
src/common/init.c
src/common/threading.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/logo.c
src/common/format.c
src/common/parsing.c
src/common/settings.c
src/common/library.c
src/common/networking.c
src/detection/os.c
src/detection/plasma.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/displayserver/displayServer.c
src/detection/displayserver/wayland.c
src/detection/displayserver/xcb.c
src/detection/displayserver/xlib.c
src/detection/displayserver/wmde.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
@@ -120,6 +221,7 @@ add_library(libfastfetch STATIC
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
@@ -128,132 +230,106 @@ add_library(libfastfetch STATIC
src/modules/date.c
src/modules/time.c
src/modules/colors.c
src/modules/opengl.c
src/modules/opencl.c
)
if(ENABLE_LIBPCI)
pkg_check_modules (LIBPCI libpci)
if(LIBPCI_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBPCI=1)
else(LIBPCI_FOUND)
message(WARNING "Package libpci not found. Building without support.")
endif(LIBPCI_FOUND)
endif(ENABLE_LIBPCI)
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()
if(ENABLE_VULKAN)
pkg_check_modules (VULKAN vulkan)
if(VULKAN_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_VULKAN=1)
else(VULKAN_FOUND)
message(WARNING "Package vulkan not found. Building without support.")
endif(VULKAN_FOUND)
endif(ENABLE_VULKAN)
add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
if(ENABLE_WAYLAND)
pkg_check_modules (WAYLAND wayland-client)
if(WAYLAND_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WAYLAND=1)
else(WAYLAND_FOUND)
message(WARNING "Package wayland-client not found. Building without support.")
endif(WAYLAND_FOUND)
endif(ENABLE_WAYLAND)
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()
if(ENABLE_XCB_RANDR)
pkg_check_modules (XCB_RANDR xcb-randr)
if(XCB_RANDR_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XCB_RANDR=1)
else(XCB_RANDR_FOUND)
message(WARNING "Package xcb-randr not found. Building without support.")
endif(XCB_RANDR_FOUND)
endif(ENABLE_XCB_RANDR)
function(ff_lib_enable VARNAME)
if(NOT ENABLE_${VARNAME})
return()
endif()
if(ENABLE_XCB)
pkg_check_modules (XCB xcb)
if(XCB_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XCB=1)
else(XCB_FOUND)
message(WARNING "Package xcb not found. Building without support.")
endif(XCB_FOUND)
endif(ENABLE_XCB)
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()
if(ENABLE_XRANDR)
pkg_check_modules (XRANDR xrandr)
if(XRANDR_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XRANDR=1)
else(XRANDR_FOUND)
message(WARNING "Package xrandr not found. Building without support.")
endif(XRANDR_FOUND)
endif(ENABLE_XRANDR)
message(WARNING "Package ${ARGV1} not found, building without support.")
endfunction()
if(ENABLE_X11)
pkg_check_modules (X11 x11)
if(X11_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_X11=1)
else(X11_FOUND)
message(WARNING "Package x11 not found. Building without support.")
endif(X11_FOUND)
endif(ENABLE_X11)
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(ENABLE_GIO)
pkg_check_modules (GIO gio-2.0)
if(GIO_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GIO=1)
else(GIO_FOUND)
message(WARNING "Package gio-2.0 not found. Building without support.")
endif(GIO_FOUND)
endif(ENABLE_GIO)
if(ENABLE_DCONF)
pkg_check_modules (DCONF dconf)
if(DCONF_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_DCONF=1)
else(DCONF_FOUND)
message(WARNING "Package dconf not found. Building without support.")
endif(DCONF_FOUND)
endif(ENABLE_DCONF)
if(ENABLE_DBUS)
pkg_check_modules (DBUS dbus-1)
if(DBUS_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_DBUS=1)
else(DBUS_FOUND)
message(WARNING "Package dbus-1 not found. Building without support.")
endif(DBUS_FOUND)
endif(ENABLE_DBUS)
if(ENABLE_XFCONF)
pkg_check_modules (XFCONF libxfconf-0)
if(XFCONF_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XFCONF=1)
else(XFCONF_FOUND)
message(WARNING "Package libxfconf-0 not found. Building without support.")
endif(XFCONF_FOUND)
endif(ENABLE_XFCONF)
if(ENABLE_RPM)
pkg_check_modules (RPM rpm)
if(RPM_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_RPM=1)
else(RPM_FOUND)
message(WARNING "Package librpm not found. Building without support.")
endif(RPM_FOUND)
endif(ENABLE_RPM)
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
PRIVATE ${LIBPCI_INCLUDE_DIRS}
PRIVATE ${VULKAN_INCLUDE_DIRS}
PRIVATE ${WAYLAND_INCLUDE_DIRS}
PRIVATE ${XCB_RANDR_INCLUDE_DIRS}
PRIVATE ${XCB_INCLUDE_DIRS}
PRIVATE ${XRANDR_INCLUDE_DIRS}
PRIVATE ${X11_INCLUDE_DIRS}
PRIVATE ${GIO_INCLUDE_DIRS}
PRIVATE ${DCONF_INCLUDE_DIRS}
PRIVATE ${DBUS_INCLUDE_DIRS}
PRIVATE ${XFCONF_INCLUDE_DIRS}
PRIVATE ${RPM_INCLUDE_DIRS}
)
target_link_libraries(libfastfetch
@@ -261,7 +337,9 @@ target_link_libraries(libfastfetch
PRIVATE Threads::Threads
)
set_target_properties(libfastfetch PROPERTIES OUTPUT_NAME "fastfetch")
######################
# Executable targets #
######################
add_executable(fastfetch
src/fastfetch.c
@@ -277,16 +355,11 @@ target_link_libraries(flashfetch
PRIVATE libfastfetch
)
# Testing
###################
# Testing targets #
###################
if (BUILD_TESTS)
add_executable(fastfetch-test-performance
tests/performance.c
)
target_link_libraries(fastfetch-test-performance
PRIVATE libfastfetch
)
add_executable(fastfetch-test-strbuf
tests/strbuf.c
)
@@ -298,58 +371,74 @@ if (BUILD_TESTS)
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
endif()
# Installation
##################
# 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
DESTINATION ${CMAKE_INSTALL_BINDIR}
TARGETS fastfetch flashfetch
DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
install(
FILES completions/bash
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions
RENAME ${CMAKE_PROJECT_NAME}
FILES "${CMAKE_SOURCE_DIR}/src/data/config_system.txt"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/${CMAKE_PROJECT_NAME}"
RENAME "config.conf"
)
install(
DIRECTORY presets
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}
FILES "${CMAKE_SOURCE_DIR}/completions/bash"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions"
RENAME "${CMAKE_PROJECT_NAME}"
)
install(
FILES ./LICENSE
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}
DIRECTORY "${CMAKE_SOURCE_DIR}/presets"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}"
)
# Packaging
install(
FILES "${CMAKE_SOURCE_DIR}/LICENSE"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}"
)
set(CPACK_GENERATOR "DEB;RPM;TGZ;ZIP")
##################
# 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_SUMMARY "Neofetch clone written in C")
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.
")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/LinusDierheimer")
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "
libpci3
libvulkan1
libwayland-client0
libxcb-randr0
xcb
libxrandr2
libx11-6
libdconf1
libglib2.0-0
libdbus-1-3
libxfconf-0-3
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)
-6
View File
@@ -11,12 +11,7 @@ Here i just add things that are easy to forget.
- `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
- [ ] Support for printing images as ascii art logos (using imlib2 and libcaca probably)
- [ ] Support for printing images in terminals that support it
- [ ] Better OS output for all possible combinations of /etc/os-release variables.
- [ ] Expose temperatures to CPU format string
- [ ] Expose temperatures to GPU format string
- [ ] Fallback GPU detection using GL (multi GPU suport somehow possible?)
- [ ] 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
@@ -25,7 +20,6 @@ Here i just add things that are easy to forget.
- [ ] 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
- [ ] RPM packaging
### General
- More presets
+47 -32
View File
@@ -1,57 +1,71 @@
# fastfetch
# <center> Fastfetch </center>
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 c to achieve much better performance, in return only Linux and Android are supported. It also uses mechanisms like multithreading and caching to finish as fast as possible.
The output on my personal machine with default configurations looks like this:
<img src="screenshots/example.png" alt="example output" width="100%"/>
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.
<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" />
## Customization
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 buildt 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).
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.
There are some presets defined for fastfech in [`presets`](presets), you can can load them with `--load-config`. They may also serve as a good example for format arguments.
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.
## Dependencies
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.
The following libraries are used if present at runtime:
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
* [`libvulkan`](https://www.vulkan.org/): 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.
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`librpm`](http://rpm.org/): Needed for rpm package count.
* [`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.
## Support status
All categories not listed here should work without needing a specific implementation.
##### 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, Disk, Battery, Player, Song, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
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
```
##### Logos
```
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Linux, Manjaro, Mint, Pop!_OS, RebornOS, Ubuntu, Void, Zorin
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.
##### Package managers
```
Pacman, dpkg, rpm, emerge, xbps, Flatpak, Snap
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, brew
```
##### WM themes
@@ -66,7 +80,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
##### Terminal fonts
```
konsole, gnome-terminal-server, tilix, xfce4-terminal, lxterminal, TTY
konsole, gnome-terminal-server, tilix, xfce4-terminal, alacritty, lxterminal, TTY
```
## Building
@@ -76,20 +90,21 @@ fastfetch uses [`cmake`](https://cmake.org/) and [`pkg-config`](https://www.free
mkdir -p build
cd build
cmake ..
cmake --build . -j$(nproc) --target fastfetch --target flashfetch
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
* [AUR](https://aur.archlinux.org/packages/fastfetch-git/): Packaged by me. Will install the fastfetch binary, bash completion and the presets. Git version
* [Manjaro Repositories](https://gitlab.manjaro.org/packages/community/fastfetch): Packaged by a manjaro maintainer. Usually a bit outdated.
* [Gentoo (Guru)](https://github.com/gentoo/guru/tree/master/app-misc/fastfetch): Packed by some other guy. May be out of date some times.
* DEB / RPM: Run `cmake -B build && cmake --build build --target package` to build the packages in build.
* Manually:
* Build: Follow the [build instructions](#building).
* Install: `sudo cmake --install build --prefix /usr/local`
### 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
+184 -49
View File
@@ -9,28 +9,38 @@ __fastfetch_complete_help()
"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"))
}
@@ -57,6 +67,41 @@ __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=(
@@ -64,6 +109,9 @@ __fastfetch_complete_option()
"${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
@@ -108,7 +156,8 @@ __fastfetch_completion()
"--list-presets"
"--list-features"
"--print-logos"
"--print-config"
"--print-config-system"
"--print-config-user"
"--print-structure"
)
@@ -122,8 +171,7 @@ __fastfetch_completion()
"--recache"
"--nocache"
"--show-errors"
"--color-logo"
"--print-remaining-logo"
"--logo-print-remaining"
"--multithreading"
"--allow-slow-operations"
"--disable-linewrap"
@@ -131,100 +179,170 @@ __fastfetch_completion()
"--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"
"--spacing"
"-s"
"--color-keys"
"--color-title"
"--separator"
"-x"
"--offsetx"
"-s"
"--structure"
"--set"
"--os-format"
"--set-keyless"
"--player-name"
"--public-ip-timeout"
"--os-key"
"--host-format"
"--os-format"
"--os-error"
"--host-key"
"--kernel-format"
"--host-format"
"--host-error"
"--kernel-key"
"--uptime-format"
"--kernel-format"
"--kernel-error"
"--uptime-key"
"--processes-format"
"--uptime-format"
"--uptime-error"
"--processes-key"
"--packages-format"
"--processes-format"
"--processes-error"
"--packages-key"
"--shell-format"
"--packages-format"
"--packages-error"
"--shell-key"
"--resolution-format"
"--shell-format"
"--shell-error"
"--resolution-key"
"--de-format"
"--resolution-format"
"--resolution-error"
"--de-key"
"--wm-format"
"--de-format"
"--de-error"
"--wm-key"
"--wm-theme-format"
"--wm-format"
"--wm-error"
"--wm-theme-key"
"--theme-format"
"--wm-theme-format"
"--wm-theme-error"
"--theme-key"
"--icons-format"
"--theme-format"
"--theme-error"
"--icons-key"
"--font-format"
"--icons-format"
"--icons-error"
"--font-key"
"--cursor-format"
"--font-format"
"--font-error"
"--cursor-key"
"--terminal-format"
"--cursor-format"
"--cursor-error"
"--terminal-key"
"--terminal-font-format"
"--terminal-format"
"--terminal-error"
"--terminal-font-key"
"--cpu-format"
"--terminal-font-format"
"--terminal-font-error"
"--cpu-key"
"--cpu-usage-format"
"--cpu-usage-key"
"--gpu-format"
"--cpu-format"
"--cpu-error"
"--cpu-useage-key"
"--cpu-useage-format"
"--cpu-useage-error"
"--gpu-key"
"--memory-format"
"--gpu-format"
"--gpu-error"
"--memory-key"
"--memory-format"
"--memory-error"
"--swap-key"
"--swap-format"
"--swap-error"
"--disk-key"
"--disk-format"
"--disk-key"
"--battery-format"
"--disk-error"
"--battery-key"
"--locale-format"
"--battery-format"
"--battery-error"
"--locale-key"
"--disk-folders"
"--disk-key"
"--local-ip-format"
"--locale-format"
"--locale-error"
"--local-ip-key"
"--public-ip-format"
"--local-ip-format"
"--local-ip-error"
"--public-ip-key"
"--player-format"
"--public-ip-format"
"--public-ip-error"
"--player-key"
"--song-format"
"--song-key"
"--player-format"
"--player-error"
"--media-key"
"--media-format"
"--media-error"
"--datetime-key"
"--datetime-format"
"--date-format"
"--datetime-error"
"--date-key"
"--time-format"
"--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-pci"
"--lib-vulkan"
"--lib-wayland"
"--lib-xcb-randr"
"--lib-xcb"
"--lib-Xrandr"
"--lib-xrandr"
"--lib-X11"
"--lib-gio"
"--lib-DConf"
"--lib-DBus"
"--lib-XFConf"
"--lib-RPM"
"--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"
"--load-config"
)
local FF_OPTIONS_LOGO=(
@@ -232,6 +350,18 @@ __fastfetch_completion()
"--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
@@ -248,9 +378,14 @@ __fastfetch_completion()
__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
+1 -1
View File
@@ -1 +1 @@
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Break:Colors
--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
+1 -1
View File
@@ -1,4 +1,4 @@
--disable-linewrap false
--multithreading false
--show-errors true
--show-errors
--recache
+2 -1
View File
@@ -1,2 +1,3 @@
--load-config verbose
--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
+29 -28
View File
@@ -1,28 +1,29 @@
--load-config all
--os-format "System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}"
--host-format "Family: {}; Name: {}; Version: {}"
--kernel-format "Sysname: {}; Release: {}; Version: {}"
--uptime-format "Days: {}; Hours: {}; Minutes: {}; Seconds: {}"
--processes-format "Count: {}"
--packages-format "All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; xbps: {}; flatpak: {}; snap: {}"
--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: {}; Pretty: {}; Vendor: {}; Logical online: {}; Logical configured: {}; Physical: {}; Cores: {}; bios: {}; scaling max: {}; scaling min: {}; info max: {}; info min: {}; cpuinfo: {}; frequency: {}"
--cpu-usage-format "Percentage: {}"
--gpu-format "Vendor: {}; Vendor pretty: {}; Name: {}; Name pretty: {}; Driver: {}"
--memory-format "Used: {}; Total: {}; Percentage: {}"
--disk-format "Used: {}; Total: {}; Files: {}; Percentage: {}"
--battery-format "Manufactor: {}; Model: {}; Technology: {}; Capacaty: {}; Status: {}"
--player-format "Name: {}"
--song-format "Song: {}; Artist: {}; Album: {}"
--datetime-format "year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}"
--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: {}
+6 -1
View File
@@ -1,4 +1,9 @@
#!/bin/env sh
#!/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 ..
Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

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.

Before

Width:  |  Height:  |  Size: 39 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
+7 -38
View File
@@ -1,4 +1,6 @@
#include "fastfetch.h"
#include "common/format.h"
#include "common/parsing.h"
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
{
@@ -32,15 +34,6 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
}
}
static inline bool placeholderValueIsForError(const FFstrbuf* placeholderValue)
{
return
ffStrbufIgnCaseCompS(placeholderValue, "e") == 0 ||
ffStrbufIgnCaseCompS(placeholderValue, "error") == 0 ||
ffStrbufIgnCaseCompS(placeholderValue, "0") == 0
;
}
static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
{
uint32_t result = UINT32_MAX;
@@ -71,17 +64,17 @@ static inline void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placehol
static inline bool formatArgSet(const FFformatarg* arg)
{
return arg->value != NULL && (
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0) ||
(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 && *(const char*)arg->value != '\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, const FFstrbuf* error, uint32_t numArgs, const FFformatarg* arguments)
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments)
{
uint32_t argCounter = 0;
@@ -128,13 +121,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
while(i < formatstr->length && formatstr->chars[i] != '}')
ffStrbufAppendC(&placeholderValue, formatstr->chars[i++]);
// test for error, if so print it
if(placeholderValueIsForError(&placeholderValue)) {
ffStrbufAppend(buffer, error);
ffStrbufDestroy(&placeholderValue);
continue;
}
// test if for stop, if so break the loop
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '-')
{
@@ -173,7 +159,7 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
else
{
ffStrbufAppendS(buffer, "\033[0m");
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
--numOpenColors;
}
@@ -186,14 +172,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
{
ffStrbufSubstrAfter(&placeholderValue, 0);
// continue if an error is set
if(placeholderValueIsForError(&placeholderValue) && error != NULL && error->length > 0)
{
++numOpenIfs;
ffStrbufDestroy(&placeholderValue);
continue;
}
uint32_t index = getArgumentIndex(&placeholderValue);
// testing for an invalid index
@@ -223,14 +201,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
{
ffStrbufSubstrAfter(&placeholderValue, 0);
//continue if an error os not set
if(placeholderValueIsForError(&placeholderValue) && (error == NULL || error->length == 0))
{
++numOpenNotIfs;
ffStrbufDestroy(&placeholderValue);
continue;
}
uint32_t index = getArgumentIndex(&placeholderValue);
// testing for an invalid index
@@ -284,6 +254,5 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
ffStrbufTrimRight(buffer, ' ');
if(numOpenColors > 0)
ffStrbufAppendS(buffer, "\033[0m");
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
+239 -100
View File
@@ -1,8 +1,15 @@
#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)
{
@@ -14,18 +21,14 @@ static void initConfigDirs(FFstate* state)
ffListInit(&state->configDirs, sizeof(FFstrbuf));
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
if(xdgConfigHome != NULL)
if(ffStrSet(xdgConfigHome))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigHome);
ffStrbufTrimRight(buffer, '/');
ffStrbufEnsureEndsWithC(buffer, '/');
}
FFstrbuf xdgConfigDirs;
ffStrbufInitA(&xdgConfigDirs, 64);
ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS"));
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
if(ffListFirstIndexComp(&state->configDirs, element, strbufEqualsAdapter) < state->configDirs.length - 1) \
--state->configDirs.length;
@@ -33,24 +36,35 @@ static void initConfigDirs(FFstate* state)
FFstrbuf* userConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userConfigHome, 64);
ffStrbufAppendS(userConfigHome, state->passwd->pw_dir);
ffStrbufAppendS(userConfigHome, "/.config");
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);
ffStrbufTrimRight(buffer, '/');
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(buffer);
startIndex = colonIndex + 1;
@@ -58,12 +72,12 @@ static void initConfigDirs(FFstate* state)
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfigHome, 64);
ffStrbufAppendS(systemConfigHome, "/etc/xdg");
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, "/etc");
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ROOT"/etc/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
@@ -80,8 +94,8 @@ static void initCacheDir(FFstate* state)
ffStrbufAppendS(&state->cacheDir, state->passwd->pw_dir);
ffStrbufAppendS(&state->cacheDir, "/.cache/");
}
else if(!ffStrbufEndsWithC(&state->cacheDir, '/'))
ffStrbufAppendC(&state->cacheDir, '/');
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
@@ -92,98 +106,91 @@ static void initCacheDir(FFstate* state)
static void initState(FFstate* state)
{
state->logoWidth = 0;
state->logoHeight = 0;
state->keysHeight = 0;
state->passwd = getpwuid(getuid());
uname(&state->utsname);
sysinfo(&state->sysinfo);
#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.color);
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.logoKeySpacing = 4;
instance->config.offsetx = 0;
instance->config.colorLogo = true;
instance->config.showErrors = false;
instance->config.recache = false;
instance->config.cacheSave = true;
instance->config.printRemainingLogo = true;
instance->config.allowSlowOperations = false;
instance->config.disableLinewrap = true;
instance->config.hideCursor = true;
instance->config.userLogoIsRaw = false;
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;
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufInit(&instance->config.logoColors[i]);
ffStrbufInitA(&instance->config.osFormat, 0);
ffStrbufInitA(&instance->config.osKey, 0);
ffStrbufInitA(&instance->config.hostFormat, 0);
ffStrbufInitA(&instance->config.hostKey, 0);
ffStrbufInitA(&instance->config.kernelFormat, 0);
ffStrbufInitA(&instance->config.kernelKey, 0);
ffStrbufInitA(&instance->config.uptimeFormat, 0);
ffStrbufInitA(&instance->config.uptimeKey, 0);
ffStrbufInitA(&instance->config.processesFormat, 0);
ffStrbufInitA(&instance->config.processesKey, 0);
ffStrbufInitA(&instance->config.packagesFormat, 0);
ffStrbufInitA(&instance->config.packagesKey, 0);
ffStrbufInitA(&instance->config.shellFormat, 0);
ffStrbufInitA(&instance->config.shellKey, 0);
ffStrbufInitA(&instance->config.resolutionFormat, 0);
ffStrbufInitA(&instance->config.resolutionKey, 0);
ffStrbufInitA(&instance->config.deFormat, 0);
ffStrbufInitA(&instance->config.deKey, 0);
ffStrbufInitA(&instance->config.wmFormat, 0);
ffStrbufInitA(&instance->config.wmKey, 0);
ffStrbufInitA(&instance->config.wmThemeFormat, 0);
ffStrbufInitA(&instance->config.wmThemeKey, 0);
ffStrbufInitA(&instance->config.themeFormat, 0);
ffStrbufInitA(&instance->config.themeKey, 0);
ffStrbufInitA(&instance->config.iconsFormat, 0);
ffStrbufInitA(&instance->config.iconsKey, 0);
ffStrbufInitA(&instance->config.fontFormat, 0);
ffStrbufInitA(&instance->config.fontKey, 0);
ffStrbufInitA(&instance->config.cursorKey, 0);
ffStrbufInitA(&instance->config.cursorFormat, 0);
ffStrbufInitA(&instance->config.terminalFormat, 0);
ffStrbufInitA(&instance->config.terminalKey, 0);
ffStrbufInitA(&instance->config.termFontFormat, 0);
ffStrbufInitA(&instance->config.termFontKey, 0);
ffStrbufInitA(&instance->config.cpuFormat, 0);
ffStrbufInitA(&instance->config.cpuKey, 0);
ffStrbufInitA(&instance->config.cpuUsageFormat, 0);
ffStrbufInitA(&instance->config.cpuUsageKey, 0);
ffStrbufInitA(&instance->config.gpuFormat, 0);
ffStrbufInitA(&instance->config.gpuKey, 0);
ffStrbufInitA(&instance->config.memoryFormat, 0);
ffStrbufInitA(&instance->config.memoryKey, 0);
ffStrbufInitA(&instance->config.diskFormat, 0);
ffStrbufInitA(&instance->config.diskKey, 0);
ffStrbufInitA(&instance->config.batteryFormat, 0);
ffStrbufInitA(&instance->config.batteryKey, 0);
ffStrbufInitA(&instance->config.localeFormat, 0);
ffStrbufInitA(&instance->config.localeKey, 0);
ffStrbufInitA(&instance->config.localIpKey, 0);
ffStrbufInitA(&instance->config.localIpFormat, 0);
ffStrbufInitA(&instance->config.publicIpKey, 0);
ffStrbufInitA(&instance->config.publicIpFormat, 0);
ffStrbufInitA(&instance->config.playerKey, 0);
ffStrbufInitA(&instance->config.playerFormat, 0);
ffStrbufInitA(&instance->config.songKey, 0);
ffStrbufInitA(&instance->config.songFormat, 0);
ffStrbufInitA(&instance->config.dateTimeKey, 0);
ffStrbufInitA(&instance->config.dateTimeFormat, 0);
ffStrbufInitA(&instance->config.dateKey, 0);
ffStrbufInitA(&instance->config.dateFormat, 0);
ffStrbufInitA(&instance->config.timeKey, 0);
ffStrbufInitA(&instance->config.timeFormat, 0);
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);
@@ -196,7 +203,17 @@ static void defaultConfig(FFinstance* instance)
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);
@@ -219,32 +236,116 @@ void ffInitInstance(FFinstance* instance)
{
initState(&instance->state);
defaultConfig(instance);
ffCacheValidate(instance);
}
static void resetConsole(bool disableLinewrap, bool hideCursor)
#if !defined(__ANDROID__)
static void* connectDisplayServerThreadMain(void* instance)
{
if(disableLinewrap)
fputs("\033[?7h", stdout);
if(hideCursor)
fputs("\033[?25h", stdout);
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(ffDisableLinewrap, ffHideCursor);
resetConsole();
exit(0);
}
void ffStart(FFinstance* instance)
{
ffDisableLinewrap = instance->config.disableLinewrap;
ffHideCursor = instance->config.hideCursor;
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;
@@ -253,21 +354,32 @@ void ffStart(FFinstance* instance)
sigaction(SIGTERM, &action, NULL);
sigaction(SIGQUIT, &action, NULL);
if(instance->config.hideCursor)
//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(instance->config.disableLinewrap)
if(ffDisableLinewrap)
fputs("\033[?7l", stdout);
ffLogoPrint(instance);
}
void ffFinish(FFinstance* instance)
{
if(instance->config.printRemainingLogo)
ffPrintRemainingLogo(instance);
if(instance->config.logo.printRemaining)
ffLogoPrintRemaining(instance);
resetConsole(instance->config.disableLinewrap, instance->config.hideCursor);
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(
@@ -301,11 +413,38 @@ void ffListFeatures()
#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
"librpm\n"
"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);
+97 -410
View File
@@ -1,424 +1,60 @@
#include "fastfetch.h"
#include "common/io.h"
#include <malloc.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
#define FF_IO_CACHE_VALUE_EXTENSION "ffcv"
#define FF_IO_CACHE_SPLIT_EXTENSION "ffcs"
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
{
ffPrintLogoLine(instance);
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
ffPrintColor(&instance->config.color);
if(customKeyFormat == NULL || customKeyFormat->length == 0)
{
fputs(moduleName, stdout);
if(moduleIndex > 0)
printf(" %hhu", moduleIndex);
}
else
{
FFstrbuf key;
ffStrbufInit(&key);
ffParseFormatString(&key, customKeyFormat, NULL, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
});
ffStrbufWriteTo(&key, stdout);
ffStrbufDestroy(&key);
}
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
ffStrbufWriteTo(&instance->config.separator, stdout);
}
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...)
{
if(!instance->config.showErrors)
return;
va_list arguments;
va_start(arguments, message);
if(formatString == NULL || formatString->length == 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
vprintf(message, arguments);
puts(FASTFETCH_TEXT_MODIFIER_RESET);
}
else
{
FF_STRBUF_CREATE(error);
ffStrbufAppendVF(&error, message, arguments);
// calloc sets all to 0 and FF_FORMAT_ARG_TYPE_NULL also has value 0 so we don't need to explictly set it
FFformatarg* nullArgs = calloc(numFormatArgs, sizeof(FFformatarg));
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, &error, numFormatArgs, nullArgs);
free(nullArgs);
ffStrbufDestroy(&error);
}
va_end(arguments);
}
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, const FFstrbuf* error, uint32_t numArgs, const FFformatarg* arguments)
{
FFstrbuf buffer;
ffStrbufInitA(&buffer, 256);
ffParseFormatString(&buffer, formatString, error, numArgs, arguments);
if(buffer.length > 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
ffStrbufPutTo(&buffer, stdout);
}
ffStrbufDestroy(&buffer);
}
void ffGetCacheFilePath(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);
}
}
void ffReadCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
static void createSubfolders(const char* fileName)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffGetCacheFilePath(instance, moduleName, extension, &path);
ffAppendFileContent(path.chars, buffer);
ffStrbufDestroy(&path);
}
ffStrbufInit(&path);
void ffWriteCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* content)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffGetCacheFilePath(instance, moduleName, extension, &path);
ffWriteFileContent(path.chars, content);
ffStrbufDestroy(&path);
}
static bool printCachedValue(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
ffReadCacheFile(instance, moduleName, FF_IO_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)
while(*fileName != '\0')
{
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
puts(content.chars + startIndex);
startIndex = nullByteIndex + 1;
++moduleCounter;
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
++fileName;
}
ffStrbufDestroy(&content);
return moduleCounter > 1;
}
static bool printCachedFormat(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
ffReadCacheFile(instance, moduleName, FF_IO_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;
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, NULL, numArgs, arguments);
++moduleCounter;
argumentCounter = 0;
}
startIndex = nullByteIndex + 1;
}
free(arguments);
ffStrbufDestroy(&content);
return moduleCounter > 1;
}
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numArgs)
{
if(instance->config.recache)
return false;
if(formatString == NULL || formatString->length == 0)
return printCachedValue(instance, moduleName, customKeyFormat);
else
return printCachedFormat(instance, moduleName, customKeyFormat, formatString, numArgs);
}
void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, FFcache* cache, const FFstrbuf* value, const FFstrbuf* formatString, uint32_t numArgs, const FFformatarg* arguments)
{
if(formatString == NULL || formatString->length == 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
ffStrbufPutTo(value, stdout);
}
else
{
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, NULL, 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 ffPrintAndSaveToCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* value, const FFstrbuf* formatString, uint32_t numArgs, const FFformatarg* arguments)
{
FFcache cache;
ffCacheOpenWrite(instance, moduleName, &cache);
ffPrintAndAppendToCache(instance, moduleName, 0, customKeyFormat, &cache, value, formatString, numArgs, arguments);
ffCacheClose(&cache);
}
void ffCacheValidate(FFinstance* instance)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffGetCacheFilePath(instance, "cacheversion", "ffv", &path);
FFstrbuf content;
ffStrbufInit(&content);
ffAppendFileContent(path.chars, &content);
bool isSameVersion = ffStrbufCompS(&content, FASTFETCH_PROJECT_VERSION) == 0;
ffStrbufDestroy(&content);
if(isSameVersion)
{
ffStrbufDestroy(&path);
return;
}
instance->config.recache = true;
FFstrbuf version;
ffStrbufInit(&version);
ffStrbufAppendS(&version, FASTFETCH_PROJECT_VERSION);
ffWriteFileContent(path.chars, &version);
ffStrbufDestroy(&version);
ffStrbufDestroy(&path);
}
void ffCacheOpenWrite(FFinstance* instance, const char* moduleName, FFcache* cache)
{
FFstrbuf cacheFileValue;
ffStrbufInitA(&cacheFileValue, 64);
ffGetCacheFilePath(instance, moduleName, FF_IO_CACHE_VALUE_EXTENSION, &cacheFileValue);
cache->value = fopen(cacheFileValue.chars, "w");
ffStrbufDestroy(&cacheFileValue);
FFstrbuf cacheFileSplit;
ffStrbufInitA(&cacheFileSplit, 64);
ffGetCacheFilePath(instance, moduleName, FF_IO_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);
}
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
{
bool* searchedValues = malloc(sizeof(bool) * numQueries);
bool allSet = true;
for(uint32_t i = 0; i < numQueries; i++)
{
if((searchedValues[i] = queries[i].buffer->length == 0))
allSet = false;
}
if(allSet)
{
free(searchedValues);
return true;
}
FILE* file = fopen(filename, "r");
if(file == NULL)
return false;
char* line = NULL;
size_t len = 0;
while (getline(&line, &len, file) != -1)
{
for(uint32_t i = 0; i < numQueries; i++)
{
if(!searchedValues[i])
continue;
uint32_t currentLength = queries[i].buffer->length;
queries[i].buffer->length = 0;
if(!ffGetPropValue(line, queries[i].start, queries[i].buffer))
queries[i].buffer->length = currentLength;
}
}
free(searchedValues);
if(line != NULL)
free(line);
fclose(file);
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;
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
{
FFstrbuf* baseDir = (FFstrbuf*) ffListGet(&instance->state.configDirs, i);
uint32_t baseDirLength = baseDir->length;
if(*relativeFile != '/')
ffStrbufAppendC(baseDir, '/');
ffStrbufAppendS(baseDir, relativeFile);
if(ffParsePropFileValues(baseDir->chars, numQueries, queries))
foundAFile = true;
ffStrbufSubstrBefore(baseDir, baseDirLength);
bool allSet = true;
for(uint32_t k = 0; k < numQueries; k++)
{
if(queries[k].buffer->length == 0)
{
allSet = false;
break;
}
}
if(allSet)
break;
}
return foundAFile;
}
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
bool ffWriteFDContent(int fd, const FFstrbuf* content)
bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
{
return write(fd, content->chars, content->length) != -1;
}
void ffWriteFileContent(const char* fileName, const FFstrbuf* content)
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
{
int fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if(fd == -1)
return;
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
ffWriteFDContent(fd, content);
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;
}
void ffAppendFDContent(int fd, FFstrbuf* buffer)
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;
@@ -430,7 +66,7 @@ void ffAppendFDContent(int fd, FFstrbuf* buffer)
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureCapacity(buffer, (buffer->allocated * 2) - 1); // -1 for null terminator
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
@@ -442,24 +78,40 @@ void ffAppendFDContent(int fd, FFstrbuf* buffer)
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return readed >= 0;
}
bool ffAppendFileContent(const char* fileName, FFstrbuf* buffer)
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;
ffAppendFDContent(fd, buffer);
bool ret = ffAppendFDBuffer(fd, buffer);
close(fd);
return true;
return ret;
}
bool ffGetFileContent(const char* fileName, FFstrbuf* buffer)
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFileContent(fileName, buffer);
return ffAppendFileBuffer(fileName, buffer);
}
// Not thread safe!
@@ -491,15 +143,50 @@ void ffSuppressIO(bool suppress)
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
}
void ffPrintColor(const FFstrbuf* colorValue)
{
fputs("\033[", stdout);
ffStrbufWriteTo(colorValue, stdout);
fputc('m', stdout);
}
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
+35 -4
View File
@@ -1,7 +1,35 @@
#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)
@@ -11,12 +39,15 @@ void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...)
va_start(defaultNames, userProvidedName);
void* result = NULL;
const char* name = va_arg(defaultNames, const char*);
while(result == NULL && name != NULL)
while(result == NULL)
{
result = dlopen(name, RTLD_LAZY);
name = va_arg(defaultNames, const char*);
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);
+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
-1399
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,7 +1,8 @@
#include "fastfetch.h"
#include "common/networking.h"
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
@@ -10,7 +11,6 @@ void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, F
struct addrinfo hints = {0};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
struct addrinfo* addr;
@@ -28,7 +28,7 @@ void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, F
{
struct timeval timev;
timev.tv_sec = 0;
timev.tv_usec = timeout * 1000; //milliseconds to microseconds
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
}
+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
+96 -328
View File
@@ -1,8 +1,102 @@
#include "fastfetch.h"
#include "common/parsing.h"
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
bool ffStrSet(const char* str)
{
if(str == NULL)
return false;
void ffGetGtkPretty(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
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)
{
@@ -81,329 +175,3 @@ void ffGetGtkPretty(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3
ffStrbufAppendS(buffer, " [GTK4]");
}
}
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 ffFontInitCopy(FFfont* font, const char* name)
{
fontInit(font);
ffStrbufAppendS(&font->name, name);
fontInitPretty(font);
}
void ffFontDestroy(FFfont* font)
{
ffStrbufDestroy(&font->pretty);
ffStrbufDestroy(&font->name);
ffStrbufDestroy(&font->size);
for(uint32_t i = 0; i < font->styles.length; i++)
ffStrbufDestroy(ffListGet(&font->styles, i));
ffListDestroy(&font->styles);
}
static bool getPropValueLine(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 ffGetPropValue(const char* line, const char* start, FFstrbuf* buffer)
{
return getPropValueLine(&line, start, buffer);
}
bool ffGetPropValueFromLines(const char* lines, const char* start, FFstrbuf* buffer)
{
while(!getPropValueLine(&lines, start, buffer))
{
while(*lines != '\0' && *lines != '\n')
++lines;
if(*lines == '\0')
return false;
//Skip '\n'
++lines;
}
return true;
}
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);
}
bool ffStrSet(const char* str)
{
if(str == NULL)
return false;
while(*str != '\0')
{
if(*str != ' ' && *str != '\t' && *str != '\n' && *str != '\r')
return true;
}
return false;
}
+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
+4 -2
View File
@@ -1,6 +1,8 @@
#include "fastfetch.h"
#include "common/processing.h"
#include "common/io.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
@@ -29,6 +31,6 @@ void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
//Parent
close(pipes[1]);
waitpid(childPid, NULL, 0);
ffAppendFDContent(pipes[0], buffer);
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
+124 -7
View File
@@ -1,6 +1,17 @@
#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; \
@@ -80,7 +91,7 @@ typedef struct GSettingsData
static const GSettingsData* getGSettingsData(FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0.so", "libgio-2.0.so.0");
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)
@@ -152,7 +163,7 @@ typedef struct DConfData
static const DConfData* getDConfData(FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf.so", "libdconf.so.1");
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)
@@ -222,7 +233,7 @@ typedef struct XFConfData
static const XFConfData* getXFConfData(FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0.so", "libxfconf-0.so.3");
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)
@@ -267,12 +278,118 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
}
#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>
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
uint32_t originalLength = result->length;
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
ffStrbufEnsureFree(result, PROP_VALUE_MAX);
result->length += (uint32_t) __system_property_get(propName, result->chars + result->length);
return result->length > originalLength;
result->chars[result->length] = '\0';
}
#endif
#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
-72
View File
@@ -1,72 +0,0 @@
#include "fastfetch.h"
#include <pthread.h>
static inline void* detectPlasmaThreadMain(void* instance)
{
ffDetectPlasma((FFinstance*)instance);
return NULL;
}
static inline void* detectGTK2ThreadMain(void* instance)
{
ffDetectGTK2((FFinstance*)instance);
return NULL;
}
static inline void* detectGTK3ThreadMain(void* instance)
{
ffDetectGTK3((FFinstance*)instance);
return NULL;
}
static inline void* detectGTK4ThreadMain(void* instance)
{
ffDetectGTK4((FFinstance*)instance);
return NULL;
}
static inline void* connectDisplayServerThreadMain(void* instance)
{
ffConnectDisplayServer((FFinstance*)instance);
return NULL;
}
static inline 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 ffStartDetectionThreads(FFinstance* instance)
{
//Android needs none of the things that are detected here
//And using gsettings sometimes hangs the program in android for some unknown reason,
//and since we don't need it we just never call it.
#ifdef __ANDROID__
return;
#endif
pthread_t startThreadsThread;
pthread_create(&startThreadsThread, NULL, startThreadsThreadMain, instance);
pthread_detach(startThreadsThread);
}
+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
+162 -64
View File
@@ -6,7 +6,7 @@
# Empty lines or lines starting with # are ignored.
# This file was shipped with $"FASTFETCH_PROJECT_VERSION$".
# Use fastfetch --print-config > ~/.config/fastfetch/config.conf to overwrite this with the current defaults
# 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".
@@ -27,38 +27,17 @@
# Get the default structure with "fastfetch --print-structure".
#--structure $"FASTFETCH_DATATEXT_STRUCTURE$"
# 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
# Multithreading option:
# Sets if fastfetch should use multiple threads to detect the values.
# Must be true or false.
# Default is true.
#--multithreading true
# Color option:
# Sets the color of the keys.
# Must be linux console color codes or the name of a color.
# Default is the primary color of the logo.
# Use "fastfetch --help color" to learn more and see examples.
#--color magenta
# Spacing option:
# Sets the amount of whitespace between the logo and keys.
# Must be an positive integer.
# Default is 4.
#--spacing 4
# Separator option:
# Sets the string placed between a key and its value.
# Can be any string.
# Default is ": ".
#--separator ": "
# Offset option:
# Sets the amount of whitespace before the logo. Can be negative to cut the logo.
# Must be an integer.
# Default is 0.
#--offsetx 0
# 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.
@@ -72,35 +51,31 @@
# Default is true.
#--hide-cursor true
# Remaing logo option:
# Sets if the remaining logo should be printed, if it is higher than the information printed.
# Must be true or false.
# Default is true.
#--print-remaining-logo 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
# Multithreading option:
# Sets if fastfetch should use multiple threads to detect the values.
# Must be true or false.
# Default is true.
#--multithreading true
# 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
# 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
# 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
# Color logo option:
# Sets if the logo should be colored.
# Must be true or false.
# Default is true.
#--color-logo true
# 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 -
# 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.
@@ -109,16 +84,72 @@
# Default is the one specified by the logo.
# Use "fastfetch --help color" to learn more and see examples.
# Valid index range is [1-9].
#--color-1 red
#--color-2 32
#--logo-color-1 red
#--logo-color-2 32
# [...]
#--color-9 yellow
#--logo-color-9 yellow
# User logo raw option:
# Sets if color replacements should be performed on the user provided logo.
# 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.
#--color-raw 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.
@@ -139,6 +170,18 @@
# 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.
@@ -163,6 +206,7 @@
#--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
@@ -171,6 +215,9 @@
#--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.
@@ -198,6 +245,7 @@
#--cpu-usage-format
#--gpu-format
#--memory-format
#--swap-format
#--disk-format
#--battery-format
#--locale-format
@@ -206,6 +254,48 @@
#--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.
@@ -221,4 +311,12 @@
#--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
+66 -94
View File
@@ -1,105 +1,67 @@
Usage: fastfetch <options>
Informative options:
-h, --help: shows this message and exits
-h <command>, --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: prints the default config and exits
--print-structure: prints the default stucture and exits
-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:
--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.
--set <key=value>: hard set the value of a key
-c <color>, --color <color>: sets the color of the keys. Must be a linux console color code or the name of a color (+)
--color-[1-9] <color>: overwrites a color of the logo. Must be a linux console color code or the name of a color
--spacing <width>: sets the distance between logo and text
-s <str>, --separator <str>: sets the separator between key and value. Default is a colon with a space
-x <offset>, --offsetx <offset>: sets the x offset. Can be negative to cut the logo, but no more than logo width.
--show-errors <?value>: print occuring errors
-r <?value> --recache <?value>: generate new cached values
--nocache <?value>: don't use cached values, but also don't overwrite existing ones
--print-remaining-logo <?value>: print the remaining logo, if it is higher than the number of lines shown
--multithreading <?value>: use multiple threads to detect values
--load-config <file>: load a config file (+)
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
--disable-linewrap <?value>: Disable linewrap during the run
--hide-cursor <?value>: Hide the cursor during the run
--logo-raw <?value>: Print a custom logo as is, without any color replacements
-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 <name>, --logo <name>: sets the shown logo. Also changes the main color accordingly. This will also load file contents as logo if the given argument is a valid path.
--color-logo <?value>: if set to false, the logo will be black / white
-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>
Format options: Provide the format string for custom output. Use fastfetch --help *-format for specific help.
--os-format <format>
--host-format <format>
--kernel-format <format>
--uptime-format <format>
--processes-format <format>
--packages-format <format>
--shell-format <format>
--resolution-format <format>
--de-format <format>
--wm-format <format>
--wm-theme-format <format>
--theme-format <format>
--icons-format <format>
--font-format <format>
--cursor-format <format>
--terminal-format <format>
--terminal-font-format <format>
--cpu-format <format>
--cpu-usage-format <format>
--gpu-format <format>
--memory-format <format>
--disk-format <format>
--battery-format <format>
--locale-format <format>
--local-ip-format <format>
--public-ip-format <format>
--player-format <format>
--song-format <format>
--datetime-format <format>
--time-format <format>
--date-format <format>
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
Key options: Provide a custom key for an output
--os-key <key>
--host-key <key>
--kernel-key <key>
--uptime-key <key>
--processes-key <key>
--packages-key <key>
--shell-key <key>
--resolution-key <key>: takes the resolution index as argument
--de-key <key>
--wm-key <key>
--wm-theme-key <key>
--theme-key <key>
--icons-key <key>
--font-key <key>
--cursor-key <key>
--terminal-key <key>
--terminal-font-key <key>
--cpu-key <key>
--cpu-usage-key <key>
--gpu-key <key>: takes the gpu index as format argument
--memory-key <key>
--disk-key <key>: takes the mount path as format argument
--battery-key <key>: takes the battery index as format argument
--locale-key <key>
--local-ip-key <key>: takes the name of this network interface as format argument
--public-ip-key <key>
--player-key <key>
--song-key <key>
--datetime-key <key>
--time-key <key>
--date-key <key>
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>
@@ -113,9 +75,18 @@ Library options: Set the path of a library to load
--lib-DConf <path>
--lib-DBus <path>
--lib-XFConf <path>
--lib-RPM <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"
@@ -125,6 +96,7 @@ Module specific options:
--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.
-6
View File
@@ -19,24 +19,18 @@ 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{/}"
There is a special variable set if an error occured during detection. You can access it with "{e}", "{error}" o
You can use ifs and not ifs with it like with an index. For example use "{?e}some text{?}", to print a text if an
To stop formatting at any point in the format string, use "{-}".
For example to print an error instead of the normal output if it occured, prefix the format string with "{?e}{e}{-
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}...{#}".
If not in a format string, fastfetch wraps errors with "{#1;31}error{#}", so you might want to do that to if you
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
This can be used to print nothing if an error occured: prefix the format string with "{?e}{-}{?}...".
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".
+5 -1
View File
@@ -15,8 +15,11 @@ Icons
Kernel
Locale
LocalIP
Media
Memory
OS
OpenCL
OpenGL
Packages
Player
Processes
@@ -24,12 +27,13 @@ PublicIP
Resolution
Separator
Shell
Song
Swap
Terminal
TerminalFont
Theme
Time
Title
Uptime
Vulkan
WM
WMTheme
+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);
}
+1 -1
View File
@@ -1,7 +1,7 @@
#include "fastfetch.h"
#include "detection/datetime.h"
#include <time.h>
#include <pthread.h>
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
+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
-132
View File
@@ -1,132 +0,0 @@
#include "displayServer.h"
#include <pthread.h>
#include <dirent.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;
}
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);
}
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance)
{
static FFDisplayServerResult 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.wmProcessName);
ffStrbufInit(&result.wmPrettyName);
ffStrbufInit(&result.wmProtocolName);
ffStrbufInit(&result.deProcessName);
ffStrbufInit(&result.dePrettyName);
ffStrbufInit(&result.deVersion);
ffListInitA(&result.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, &result);
//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(result.resolutions.length == 0)
ffdsConnectXcbRandr(instance, &result);
if(result.resolutions.length == 0)
ffdsConnectXrandr(instance, &result);
if(result.resolutions.length == 0)
ffdsConnectXcb(instance, &result);
if(result.resolutions.length == 0)
ffdsConnectXlib(instance, &result);
//This resolution detection method is display server independent.
//Use it if all connections failed
if(result.resolutions.length == 0)
parseDRM(&result);
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(instance, &result);
pthread_mutex_unlock(&mutex);
return &result;
}
@@ -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);
}
@@ -3,15 +3,12 @@
#ifndef FASTFETCH_INCLUDED_DISPLAYSERVER
#define FASTFETCH_INCLUDED_DISPLAYSERVER
#include "fastfetch.h"
#include "detection/displayserver/displayserver.h"
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate);
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
+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);
}
@@ -1,8 +1,15 @@
#include "displayServer.h"
#include <dirent.h>
#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 <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
static const char* parseEnv()
{
@@ -40,6 +47,11 @@ static const char* parseEnv()
if(getenv("TDE_FULL_SESSION") != NULL)
return "Trinity";
if(
getenv("WAYLAND_DISPLAY") != NULL &&
ffFileExists("/mnt/wslg/", S_IFDIR)
) return "WSLg";
return NULL;
}
@@ -48,8 +60,23 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce
if(!ffStrSet(processName))
return;
if(strcasecmp(processName, "kwin_wayland") == 0 || strcasecmp(processName, "kwin_x11") == 0 || strcasecmp(processName, "kwin") == 0)
ffStrbufSetS(&result->wmPrettyName, "KWin");
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)
@@ -64,10 +91,6 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce
ffStrbufSetS(&result->wmPrettyName, "Marco");
else if(strcasecmp(processName, "xmonad") == 0)
ffStrbufSetS(&result->wmPrettyName, "XMonad");
else if(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( // WMs where the pretty name matches the process name
strcasecmp(processName, "dwm") == 0 ||
strcasecmp(processName, "bspwm") == 0 ||
@@ -98,7 +121,15 @@ static void getKDE(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "plasmashell");
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
ffParsePropFile("/usr/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
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"));
}
@@ -106,14 +137,14 @@ static void getGnome(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "gnome-shell");
ffStrbufSetS(&result->dePrettyName, "GNOME");
ffParsePropFile("/usr/share/gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
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("/usr/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
}
static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
@@ -130,7 +161,7 @@ static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
FFstrbuf micro;
ffStrbufInit(&micro);
ffParsePropFileValues("/usr/share/mate-about/mate-version.xml", 3, (FFpropquery[]) {
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR"/share/mate-about/mate-version.xml", 3, (FFpropquery[]) {
{"<platform>", &major},
{"<minor>", &minor},
{"<micro>", &micro}
@@ -159,7 +190,7 @@ static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "xfce4-session");
ffStrbufSetS(&result->dePrettyName, "Xfce4");
ffParsePropFile("/usr/share/gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
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)
{
@@ -180,12 +211,12 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, "LXQt");
ffParsePropFile("/usr/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile("/usr/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile("/usr/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
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)
{
@@ -197,7 +228,7 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
});
result->deVersion.length = 0; //don't set '\0' byte
ffGetPropValueFromLines(result->deVersion.chars , "liblxqt", &result->deVersion);
ffParsePropLines(result->deVersion.chars , "liblxqt", &result->deVersion);
}
FFstrbuf wmProcessNameBuffer;
@@ -321,7 +352,7 @@ static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* re
//Don't check for processes not owend by the current user.
ffStrbufAppendS(&procPath, "/loginuid");
ffGetFileContent(procPath.chars, &loginuid);
ffReadFileBuffer(procPath.chars, &loginuid);
if(ffStrbufComp(&userID, &loginuid) != 0)
{
ffStrbufSubstrBefore(&procPath, procPathLength);
@@ -332,7 +363,7 @@ static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* re
//We check the cmdline for the process name, because it is not trimmed.
ffStrbufAppendS(&procPath, "/cmdline");
ffGetFileContent(procPath.chars, &processName);
ffReadFileBuffer(procPath.chars, &processName);
ffStrbufSubstrBeforeFirstC(&processName, '\0'); //Trim the arguments
ffStrbufSubstrAfterLastC(&processName, '/');
@@ -363,7 +394,7 @@ void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result)
getWMProtocolNameFromEnv(result);
//We don't want to detect anything in TTY
//This can't happen if a X11 connection succeeded, so we don't need to clear wmProcessName
//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;
@@ -1,8 +1,10 @@
#include "displayServer.h"
#include "displayserver_linux.h"
#ifdef FF_HAVE_XCB
#include <xcb/xcb.h>
#include "common/library.h"
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
typedef struct XcbPropertyData
{
@@ -16,12 +18,12 @@ typedef struct XcbPropertyData
static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyData)
{
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_intern_atom, xcb_intern_atom, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_intern_atom_reply, xcb_intern_atom_reply, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property, xcb_get_property, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property_reply, xcb_get_property_reply, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property_value, xcb_get_property_value, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property_value_length, xcb_get_property_value_length, false)
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;
}
@@ -60,7 +62,7 @@ static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection,
static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0)
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");
@@ -89,7 +91,7 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcb, instance->config.libXcb, , "libxcb.so", "libxcb.so.1")
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,)
@@ -213,15 +215,15 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
return false;
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
free(crtcInfoReply);
return res ? true : ffdsAppendResolution(
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)
@@ -324,7 +326,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcbRandr, instance->config.libXcbRandr, , "libxcb-randr.so", "libxcb-randr.so.0")
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,)
@@ -333,23 +335,23 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu
XcbRandrData data;
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_resources, xcb_randr_get_screen_resources,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_resources_reply, xcb_randr_get_screen_resources_reply,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_resources_modes_iterator, xcb_randr_get_screen_resources_modes_iterator,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_info, xcb_randr_get_screen_info,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_info_reply, xcb_randr_get_screen_info_reply,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_mode_info_next, xcb_randr_mode_info_next,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_monitors, xcb_randr_get_monitors,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_monitors_reply, xcb_randr_get_monitors_reply,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_monitors_monitors_iterator, xcb_randr_get_monitors_monitors_iterator,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_monitor_info_next, xcb_randr_monitor_info_next,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_monitor_info_outputs_length, xcb_randr_monitor_info_outputs_length,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_monitor_info_outputs, xcb_randr_monitor_info_outputs,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_output_next, xcb_randr_output_next,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_output_info, xcb_randr_get_output_info,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_output_info_reply, xcb_randr_get_output_info_reply,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_crtc_info, xcb_randr_get_crtc_info,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_crtc_info_reply, xcb_randr_get_crtc_info_reply,)
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);
@@ -1,6 +1,8 @@
#include "displayServer.h"
#include "displayserver_linux.h"
#ifdef FF_HAVE_X11
#include "common/library.h"
#include "common/parsing.h"
#include <X11/Xlib.h>
typedef struct X11PropertyData
@@ -11,8 +13,8 @@ typedef struct X11PropertyData
static bool x11InitPropertyData(void* libraryHandle, X11PropertyData* propertyData)
{
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffXInternAtom, XInternAtom, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffXGetWindowProperty, XGetWindowProperty, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XInternAtom, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XGetWindowProperty, false)
return true;
}
@@ -34,7 +36,7 @@ static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Wi
static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0)
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");
@@ -53,7 +55,7 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(x11, instance->config.libX11, , "libX11.so", "libX11.so.6", "libX11-xcb.so", "libX11-xcb.so.1")
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,)
@@ -161,15 +163,15 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
return false;
bool res = xrandrHandleMode(data, crtcInfo->mode);
data->ffXRRFreeCrtcInfo(crtcInfo);
return res ? true : ffdsAppendResolution(
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)
@@ -257,24 +259,24 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xrandr, instance->config.libXrandr, , "libXrandr.so", "libXrandr.so.2")
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_ADRESS(xrandr, data.ffXRRGetScreenInfo, XRRGetScreenInfo,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRConfigCurrentRate, XRRConfigCurrentRate,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetMonitors, XRRGetMonitors,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetScreenResources, XRRGetScreenResources,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetOutputInfo, XRRGetOutputInfo,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetCrtcInfo, XRRGetCrtcInfo,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeCrtcInfo, XRRFreeCrtcInfo,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeOutputInfo, XRRFreeOutputInfo,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenResources, XRRFreeScreenResources,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeMonitors, XRRFreeMonitors,);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenConfigInfo, XRRFreeScreenConfigInfo,);
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);
-166
View File
@@ -1,166 +0,0 @@
#include "displayServer.h"
#include <string.h>
#ifdef FF_HAVE_WAYLAND
#include <wayland-client.h>
#include <pthread.h>
typedef struct WaylandData
{
const FFinstance* instance;
FFlist* results;
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
const struct wl_interface* ffwl_output_interface;
struct wl_output_listener output_listener;
} WaylandData;
static void waylandGlobalRemoveListener(void* data, struct wl_registry* wl_registry, uint32_t name){
FF_UNUSED(data, wl_registry, name);
}
static void waylandOutputGeometryListener(void* data, struct wl_output* wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform)
{
FF_UNUSED(data, wl_output, x, y, physical_width, physical_height, subpixel, make, model, transform);
}
static void waylandOutputDoneListener(void* data, struct wl_output* wl_output)
{
FF_UNUSED(data, wl_output);
}
static void waylandOutputScaleListener(void* data, struct wl_output* wl_output, int32_t factor)
{
FF_UNUSED(data, wl_output, factor);
}
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
{
if(!(flags & WL_OUTPUT_MODE_CURRENT))
return;
WaylandData* wldata = (WaylandData*) data;
wldata->ffwl_proxy_destroy((struct wl_proxy*) output);
if(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)
{
if(strcmp(interface, "wl_output") == 0)
{
WaylandData* wldata = (WaylandData*) data;
struct wl_output* output = (struct wl_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;
wldata->ffwl_proxy_add_listener((struct wl_proxy*) output, (void(**)(void)) &wldata->output_listener, data);
}
}
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result)
{
if(getenv("XDG_RUNTIME_DIR") == NULL)
return;
FF_LIBRARY_LOAD(wayland, instance->config.libWayland, , "libwayland-client.so", "libwayland-client.so.0")
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect,)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch,)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip,)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor,)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect,)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface,)
WaylandData data;
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_marshal_constructor_versioned, wl_proxy_marshal_constructor_versioned,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_add_listener, wl_proxy_add_listener,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_output_interface, wl_output_interface,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_destroy, wl_proxy_destroy,)
struct wl_display* display = ffwl_display_connect(NULL);
if(display == NULL)
{
dlclose(wayland);
return;
}
struct wl_registry* registry = (struct wl_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;
}
data.instance = instance;
data.results = &result->resolutions;
struct wl_registry_listener regestry_listener;
regestry_listener.global = waylandGlobalAddListener;
regestry_listener.global_remove = waylandGlobalRemoveListener;
data.output_listener.geometry = waylandOutputGeometryListener;
data.output_listener.mode = waylandOutputModeListener;
data.output_listener.done = waylandOutputDoneListener;
data.output_listener.scale = waylandOutputScaleListener;
data.ffwl_proxy_add_listener((struct wl_proxy*) registry, (void(**)(void)) &regestry_listener, &data);
ffwl_display_dispatch(display);
ffwl_display_roundtrip(display);
data.ffwl_proxy_destroy((struct wl_proxy*) registry);
ffwl_display_disconnect(display);
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);
}
#else
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_UNUSED(instance);
//We try to detect wayland already here, so the x11 methods only to resolution detection.
//Wayland requires this to be set
if(getenv("XDG_RUNTIME_DIR") == NULL)
return;
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.
//Set the protocol name and use DRM for resolution detection.
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
}
#endif
+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
}
+38 -69
View File
@@ -1,4 +1,8 @@
#include "fastfetch.h"
#include "detection/gtk.h"
#include "common/properties.h"
#include "common/settings.h"
#include "detection/displayserver/displayserver.h"
#include <pthread.h>
@@ -10,7 +14,7 @@ static inline bool allPropertiesSet(FFGTKResult* result)
result->font.length > 0;
}
static inline void applyGTKDConfSettings(FFGTKResult* result, const char* themeName, const char* iconsName, const char* fontName, const char* cursorTheme, int cursorSize)
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);
@@ -28,7 +32,7 @@ static inline void applyGTKDConfSettings(FFGTKResult* result, const char* themeN
ffStrbufAppendF(&result->cursorSize, "%i", cursorSize);
}
static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
static void detectGTKFromSettings(FFinstance* instance, FFGTKResult* result)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -45,7 +49,7 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
if(init)
{
pthread_mutex_unlock(&mutex);
applyGTKDConfSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
return;
}
@@ -53,7 +57,15 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0)
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;
@@ -69,26 +81,17 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
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;
}
//Fallback + Gnome impl
if(themeName == NULL)
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;
if(iconsName == NULL)
iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
if(fontName == NULL)
fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
if(cursorTheme == NULL)
cursorTheme = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
if(cursorSize <= 0)
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);
applyGTKDConfSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
}
static void detectGTKFromConfigFile(const char* filename, FFGTKResult* result)
@@ -104,15 +107,10 @@ static void detectGTKFromConfigFile(const char* filename, FFGTKResult* result)
static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFGTKResult* result)
{
//In case of an empty env variable
ffStrbufTrim(configDir, ' ');
if(configDir->length == 0)
return;
uint32_t configDirLength = configDir->length;
// <configdir>/gtk-<version>.0/settings.ini
ffStrbufAppendS(configDir, "/gtk-");
ffStrbufAppendS(configDir, "gtk-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0/settings.ini");
detectGTKFromConfigFile(configDir->chars, result);
@@ -121,7 +119,7 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
return;
// <configdir>/gtk-<version>.0/gtkrc
ffStrbufAppendS(configDir, "/gtk-");
ffStrbufAppendS(configDir, "gtk-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0/gtkrc");
detectGTKFromConfigFile(configDir->chars, result);
@@ -130,7 +128,7 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
return;
// <configdir>/gtkrc-<version>.0
ffStrbufAppendS(configDir, "/gtkrc-");
ffStrbufAppendS(configDir, "gtkrc-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0");
detectGTKFromConfigFile(configDir->chars, result);
@@ -139,66 +137,37 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
return;
// <configdir>/.gtkrc-<version>.0
ffStrbufAppendS(configDir, "/.gtkrc-");
ffStrbufAppendS(configDir, ".gtkrc-");
ffStrbufAppendS(configDir, version);
ffStrbufAppendS(configDir, ".0");
detectGTKFromConfigFile(configDir->chars, result);
ffStrbufSubstrBefore(configDir, configDirLength);
}
static void detectGTK(FFinstance* instance, const char* version, const char* envVariable, FFGTKResult* result)
static void detectGTK(FFinstance* instance, const char* version, FFGTKResult* result)
{
FFstrbuf buffer;
ffStrbufInitA(&buffer, 128);
// From ENV: GTK*_RC_FILES
ffStrbufSetS(&buffer, getenv(envVariable));
uint32_t startIndex = 0;
while (startIndex < buffer.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&buffer, startIndex, ':');
buffer.chars[colonIndex] = '\0';
detectGTKFromConfigFile(buffer.chars + startIndex, result);
if(allPropertiesSet(result))
{
ffStrbufDestroy(&buffer);
return;
}
startIndex = colonIndex + 1;
}
//From DConf / GSettings
detectGTKFromDConf(instance, result);
//Mate, Cinnamon and Gnome use dconf to save theme config
//On other DEs, this will do nothing
detectGTKFromSettings(instance, result);
if(allPropertiesSet(result))
{
ffStrbufDestroy(&buffer);
return;
}
//From config dirs
//We need to do this because we use multiple threads on configDirs
FFstrbuf baseDirCopy;
ffStrbufInitA(&baseDirCopy, 64);
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
{
FFstrbuf* baseDir = (FFstrbuf*) ffListGet(&instance->state.configDirs, i);
ffStrbufSet(&baseDirCopy, baseDir);
detectGTKFromConfigDir(&baseDirCopy, version, result);
ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
detectGTKFromConfigDir(&baseDir, version, result);
if(allPropertiesSet(result))
break;
}
ffStrbufDestroy(&baseDirCopy);
ffStrbufDestroy(&buffer);
ffStrbufDestroy(&baseDir);
}
#define FF_CALCULATE_GTK_IMPL(version) \
#define FF_DETECT_GTK_IMPL(version) \
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
static FFGTKResult result; \
static bool init = false; \
@@ -213,23 +182,23 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env
ffStrbufInit(&result.font); \
ffStrbufInit(&result.cursor); \
ffStrbufInit(&result.cursorSize); \
detectGTK(instance, #version, "GTK"#version"_RC_FILES", &result); \
detectGTK(instance, #version, &result); \
pthread_mutex_unlock(&mutex); \
return &result;
const FFGTKResult* ffDetectGTK2(FFinstance* instance)
{
FF_CALCULATE_GTK_IMPL(2)
FF_DETECT_GTK_IMPL(2)
}
const FFGTKResult* ffDetectGTK3(FFinstance* instance)
{
FF_CALCULATE_GTK_IMPL(3)
FF_DETECT_GTK_IMPL(3)
}
const FFGTKResult* ffDetectGTK4(FFinstance* instance)
{
FF_CALCULATE_GTK_IMPL(4)
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
+41 -35
View File
@@ -1,11 +1,15 @@
#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) \
@@ -68,8 +72,11 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
while(true)
{
if((foundAValue = getValue(&subIter, result, data)))
if(getValue(&subIter, result, data))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(subIter);
}
@@ -83,7 +90,7 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
static DBusMessage* getReply(DBusMessage* request, DBusData* data)
{
DBusPendingCall* pendingCall = NULL;
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, DBUS_TIMEOUT_USE_DEFAULT);
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;
@@ -196,7 +203,7 @@ static bool getBusProperties(const char* busName, FFMediaResult* result, DBusDat
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)
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0)
break;
FF_DBUS_ITER_CONTINUE(arrayIterator)
@@ -212,12 +219,15 @@ static bool getBusProperties(const char* busName, FFMediaResult* result, DBusDat
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;
}
@@ -226,13 +236,10 @@ static void getCustomBus(FFinstance* instance, FFMediaResult* result, DBusData*
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
{
ffStrbufAppendS(&result->busNameShort, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
getBusProperties(instance->config.playerName.chars, result, data);
return;
}
ffStrbufAppend(&result->busNameShort, &instance->config.playerName);
FFstrbuf busName;
ffStrbufInit(&busName);
ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX);
@@ -243,6 +250,12 @@ static void getCustomBus(FFinstance* instance, FFMediaResult* result, DBusData*
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;
@@ -270,10 +283,7 @@ static void getBestBus(FFMediaResult* result, DBusData* data)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(getBusProperties(busName, result, data))
{
ffStrbufAppendS(&result->busNameShort, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
break;
}
FF_DBUS_ITER_CONTINUE(arrayIterator)
}
@@ -285,23 +295,23 @@ static void getMedia(FFinstance* instance, FFMediaResult* result)
{
DBusData data;
FF_LIBRARY_LOAD(dbus, instance->config.libDBus, , "libdbus-1.so", "libdbus-1.so.3");
FF_LIBRARY_LOAD(dbus, instance->config.libDBus, , "libdbus-1.so", 4);
FF_LIBRARY_LOAD_SYMBOL(dbus, dbus_bus_get,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_new_method_call, dbus_message_new_method_call,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_init, dbus_message_iter_init,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_init_append, dbus_message_iter_init_append,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_append_basic, dbus_message_iter_append_basic,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_get_arg_type, dbus_message_iter_get_arg_type,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_get_basic, dbus_message_iter_get_basic,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_recurse, dbus_message_iter_recurse,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_has_next, dbus_message_iter_has_next,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_next, dbus_message_iter_next,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_unref, dbus_message_unref,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_connection_send_with_reply, dbus_connection_send_with_reply,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_connection_flush, dbus_connection_flush,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_pending_call_block, dbus_pending_call_block,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_pending_call_steal_reply, dbus_pending_call_steal_reply,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_pending_call_unref, dbus_pending_call_unref,)
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)
@@ -345,19 +355,15 @@ const FFMediaResult* ffDetectMedia(FFinstance* instance)
getMedia(instance, &result);
#endif
//Set busNameShort if a custom player was given, but loading dbus failed
if(instance->config.playerName.length > 0 && result.busNameShort.length == 0)
//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.busNameShort, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result.player, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
else
ffStrbufAppend(&result.busNameShort, &instance->config.playerName);
ffStrbufAppend(&result.player, &instance->config.playerName);
}
//Set player to busNameShort, if detection failed
if(result.player.length == 0)
ffStrbufAppend(&result.player, &result.busNameShort);
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);
);
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#ifndef FF_INCLUDED_detection_memory_memory
#define FF_INCLUDED_detection_memory_memory
#include "fastfetch.h"
typedef struct FFMemoryStorage
{
uint64_t bytesUsed;
uint64_t bytesTotal;
uint8_t percentage;
} FFMemoryStorage;
typedef struct FFMemoryResult
{
FFMemoryStorage ram;
FFMemoryStorage swap;
} FFMemoryResult;
const FFMemoryResult* ffDetectMemory();
#endif
+24
View File
@@ -0,0 +1,24 @@
#include "memory.h"
#include "common/settings.h"
#include <string.h>
#include <mach/mach.h>
void ffDetectMemoryImpl(FFMemoryResult* memory)
{
memset(memory, 0, sizeof(FFMemoryResult));
memory->ram.bytesTotal = (uint64_t) ffSettingsGetAppleInt64("hw.memsize", 0);
uint32_t pagesize = (uint32_t) ffSettingsGetAppleInt("hw.pagesize", 0);
if(pagesize == 0)
return;
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
vm_statistics_data_t vmstat;
if(host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) (&vmstat), &count) != KERN_SUCCESS)
return;
memory->ram.bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * pagesize;
}
+48
View File
@@ -0,0 +1,48 @@
#include "memory.h"
#include <stdlib.h>
#include <string.h>
void ffDetectMemoryImpl(FFMemoryResult* memory)
{
memset(memory, 0, sizeof(FFMemoryResult));
FILE* meminfo = fopen("/proc/meminfo", "r");
if(meminfo == NULL)
return;
char* line = NULL;
size_t len = 0;
uint32_t memTotal = 0,
shmem = 0,
memFree = 0,
buffers = 0,
cached = 0,
sReclaimable = 0,
swapTotal = 0,
swapFree = 0;
while (getline(&line, &len, meminfo) != EOF)
{
sscanf(line, "MemTotal: %u", &memTotal);
sscanf(line, "Shmem: %u", &shmem);
sscanf(line, "MemFree: %u", &memFree);
sscanf(line, "Buffers: %u", &buffers);
sscanf(line, "Cached: %u", &cached);
sscanf(line, "SReclaimable: %u", &sReclaimable);
sscanf(line, "SwapTotal: %u", &swapTotal);
sscanf(line, "SwapFree: %u", &swapFree);
}
if(line != NULL)
free(line);
fclose(meminfo);
memory->ram.bytesTotal = memTotal * (uint64_t) 1024;
memory->ram.bytesUsed = (memTotal + shmem - memFree - buffers - cached - sReclaimable) * (uint64_t) 1024;
memory->swap.bytesTotal = swapTotal * (uint64_t) 1024;
memory->swap.bytesUsed = (swapTotal - swapFree) * (uint64_t) 1024;
}
-83
View File
@@ -1,83 +0,0 @@
#include "fastfetch.h"
#include <pthread.h>
#if !defined(__ANDROID__)
static void parseFile(const char* fileName, FFOSResult* result)
{
if(result->name.length > 0 && result->prettyName.length > 0)
return;
ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
{"NAME =", &result->name},
{"DISTRIB_DESCRIPTION =", &result->prettyName},
{"PRETTY_NAME =", &result->prettyName},
{"DISTRIB_ID =", &result->id},
{"ID =", &result->id},
{"ID_LIKE =", &result->idLike},
{"VARIANT =", &result->variant},
{"VARIANT_ID =", &result->variantID},
{"DISTRIB_RELEASE =", &result->version},
{"VERSION =", &result->version},
{"VERSION_ID =", &result->versionID},
{"VERSION_CODENAME =", &result->codename},
{"BUILD_ID =", &result->buildID}
});
}
#endif
const FFOSResult* ffDetectOS(FFinstance* instance)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static FFOSResult result;
static bool init = false;
pthread_mutex_lock(&mutex);
if(init)
{
pthread_mutex_unlock(&mutex);
return &result;
}
init = true;
ffStrbufInit(&result.systemName);
ffStrbufInit(&result.name);
ffStrbufInit(&result.prettyName);
ffStrbufInit(&result.id);
ffStrbufInit(&result.idLike);
ffStrbufInit(&result.variant);
ffStrbufInit(&result.variantID);
ffStrbufInit(&result.version);
ffStrbufInit(&result.versionID);
ffStrbufInit(&result.codename);
ffStrbufInit(&result.buildID);
ffStrbufInit(&result.architecture);
ffStrbufSetS(&result.systemName, instance->state.utsname.sysname);
ffStrbufSetS(&result.architecture, instance->state.utsname.machine);
#if !__ANDROID__
if(instance->config.osFile.length > 0)
{
parseFile(instance->config.osFile.chars, &result);
}
else
{
parseFile("/etc/os-release", &result);
parseFile("/usr/lib/os-release", &result);
parseFile("/etc/lsb-release", &result);
}
#else
ffStrbufSetS(&result.name, "Android");
ffStrbufSetS(&result.id, "android");
ffSettingsGetAndroidProperty("ro.build.version.release", &result.versionID);
ffSettingsGetAndroidProperty("ro.build.version.release", &result.version);
ffSettingsGetAndroidProperty("ro.build.version.codename", &result.codename);
ffSettingsGetAndroidProperty("ro.build.id", &result.buildID);
#endif
pthread_mutex_unlock(&mutex);
return &result;
}
+11
View File
@@ -0,0 +1,11 @@
#include "os.h"
#include "detection/internal.h"
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance);
const FFOSResult* ffDetectOS(const FFinstance* instance)
{
FF_DETECTION_INTERNAL_GUARD(FFOSResult,
ffDetectOSImpl(&result, instance)
);
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#ifndef FF_INCLUDED_detection_os_os
#define FF_INCLUDED_detection_os_os
#include "fastfetch.h"
typedef struct FFOSResult
{
FFstrbuf name;
FFstrbuf prettyName;
FFstrbuf id;
FFstrbuf idLike;
FFstrbuf variant;
FFstrbuf variantID;
FFstrbuf version;
FFstrbuf versionID;
FFstrbuf codename;
FFstrbuf buildID;
FFstrbuf systemName;
FFstrbuf architecture;
} FFOSResult;
const FFOSResult* ffDetectOS(const FFinstance* instance);
#endif
+38
View File
@@ -0,0 +1,38 @@
#include "os.h"
#include "common/settings.h"
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
{
FF_UNUSED(instance);
ffStrbufInit(&os->name);
ffStrbufSetS(&os->name, "Android");
ffStrbufInit(&os->prettyName);
ffStrbufSetS(&os->prettyName, "Android");
ffStrbufInit(&os->id);
ffStrbufSetS(&os->id, "android");
ffStrbufInit(&os->version);
ffSettingsGetAndroidProperty("ro.build.version.release", &os->version);
ffStrbufInit(&os->versionID);
ffSettingsGetAndroidProperty("ro.build.version.release", &os->versionID);
ffStrbufInit(&os->codename);
ffSettingsGetAndroidProperty("ro.build.version.codename", &os->codename);
ffStrbufInit(&os->buildID);
ffSettingsGetAndroidProperty("ro.build.id", &os->buildID);
ffStrbufInit(&os->systemName);
ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
ffStrbufInit(&os->architecture);
ffStrbufSetS(&os->architecture, instance->state.utsname.machine);
ffStrbufInitA(&os->idLike, 0);
ffStrbufInitA(&os->variant, 0);
ffStrbufInitA(&os->variantID, 0);
}
+93
View File
@@ -0,0 +1,93 @@
#include "os.h"
#include "common/properties.h"
#include "common/settings.h"
#include <stdlib.h>
#include <sys/sysctl.h>
typedef enum PListKey
{
PLIST_KEY_NAME,
PLIST_KEY_VERSION,
PLIST_KEY_BUILD,
PLIST_KEY_OTHER
} PListKey;
static void parseFile(FFOSResult* os)
{
FILE* plist = fopen("/System/Library/CoreServices/SystemVersion.plist", "r");
if(plist == NULL)
return;
char* line = NULL;
size_t len = 0;
PListKey key = PLIST_KEY_OTHER;
FFstrbuf keyBuffer;
ffStrbufInit(&keyBuffer);
while(getline(&line, &len, plist) != EOF)
{
if(ffParsePropLine(line, "<key>", &keyBuffer))
{
if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductName") == 0)
key = PLIST_KEY_NAME;
else if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductUserVisibleVersion") == 0)
key = PLIST_KEY_VERSION;
else if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductBuildVersion") == 0)
key = PLIST_KEY_BUILD;
else
key = PLIST_KEY_OTHER;
ffStrbufClear(&keyBuffer);
continue;
}
if(key == PLIST_KEY_NAME)
ffParsePropLine(line, "<string>", &os->name);
else if(key == PLIST_KEY_VERSION)
ffParsePropLine(line, "<string>", &os->version);
else if(key == PLIST_KEY_BUILD)
ffParsePropLine(line, "<string>", &os->buildID);
}
ffStrbufDestroy(&keyBuffer);
if(line != NULL)
free(line);
fclose(plist);
}
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
{
FF_UNUSED(instance);
ffStrbufInit(&os->name);
ffStrbufInit(&os->version);
ffStrbufInit(&os->buildID);
ffStrbufInit(&os->id);
ffStrbufInit(&os->prettyName);
ffStrbufInit(&os->versionID);
ffStrbufInit(&os->systemName);
ffStrbufInit(&os->architecture);
ffStrbufInitA(&os->codename, 0);
ffStrbufInitA(&os->idLike, 0);
ffStrbufInitA(&os->variant, 0);
ffStrbufInitA(&os->variantID, 0);
parseFile(os);
if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS"))
ffStrbufAppendS(&os->id, "macos");
if(os->version.length == 0)
ffSettingsGetAppleProperty("kern.osproductversion", &os->version);
//TODO map version to pretty name
ffStrbufAppend(&os->prettyName, &os->name);
ffStrbufAppend(&os->versionID, &os->version);
ffSettingsGetAppleProperty("kern.ostype", &os->systemName);
ffSettingsGetAppleProperty("hw.machine", &os->architecture);
}

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