Compare commits

...

129 Commits

Author SHA1 Message Date
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
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
95 changed files with 3628 additions and 1760 deletions
+10 -4
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
@@ -27,9 +34,8 @@ 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`.
If this isn't possible (or too 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)
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
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 libmagickcore-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
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
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 libmagickcore-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
-2
View File
@@ -5,5 +5,3 @@
cscope.*
tags
fastfetch.kdev4
**/*.deb
packaging/deb/fastfetch
+147 -54
View File
@@ -1,20 +1,13 @@
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs
project(fastfetch
VERSION 1.3.1
VERSION 1.5.4
LANGUAGES C
)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
# This is set to off by github actions for release builds
OPTION(SET_TWEAK "Add tweak to project version" ON)
# Also create test executables
OPTION(BUILD_TESTS "Build tests" OFF)
#####################
# Configure options #
#####################
OPTION(ENABLE_LIBPCI "Enable libpci" ON)
OPTION(ENABLE_VULKAN "Enable vulkan" ON)
@@ -27,19 +20,50 @@ 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_SQLITE3 "Enable sqlite3" ON)
OPTION(ENABLE_RPM "Enable rpm" ON)
OPTION(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON)
OPTION(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON)
OPTION(ENABLE_ZLIB "Enable zlib" ON)
OPTION(ENABLE_CHAFA "Enable chafa" ON)
OPTION(ENABLE_EGL "Enable egl" ON)
OPTION(ENABLE_GLX "Enable glx" ON)
OPTION(ENABLE_OSMESA "Enable osmesa" ON)
OPTION(ENABLE_OPENCL "Enable opencl" ON)
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)
####################
# 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")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-Wl,-O3")
# These variables are mainly here for android, which has a different root fs structure.
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 "")
@@ -64,15 +88,10 @@ if(NOT TARGET_DIR_HOME)
endif()
endif()
function(fastfetch_load_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
string(REPLACE "\n" "\\n" TEMP "${TEMP}")
string(REPLACE "\"" "\\\"" TEMP "${TEMP}")
string(REPLACE "$\\" "" TEMP "${TEMP}")
set("${OUTVAR}" "${TEMP}" PARENT_SCOPE)
endfunction(fastfetch_load_text)
#################
# 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
@@ -83,6 +102,18 @@ if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
endif()
#############
# Text data #
#############
function(fastfetch_load_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
string(REPLACE "\n" "\\n" TEMP "${TEMP}")
string(REPLACE "\"" "\\\"" TEMP "${TEMP}")
string(REPLACE "$\\" "" TEMP "${TEMP}")
set("${OUTVAR}" "${TEMP}" PARENT_SCOPE)
endfunction(fastfetch_load_text)
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
fastfetch_load_text(src/data/config.txt DATATEXT_CONFIG)
fastfetch_load_text(src/data/modules.txt DATATEXT_MODULES)
@@ -91,11 +122,17 @@ 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)
# Init CMake targets
#######################
# libfastfetch target #
#######################
add_library(libfastfetch STATIC
add_library(libfastfetch OBJECT
src/util/FFstrbuf.c
src/util/FFlist.c
src/util/FFvaluestore.c
@@ -121,8 +158,10 @@ add_library(libfastfetch STATIC
src/detection/plasma.c
src/detection/gtk.c
src/detection/terminalShell.c
src/detection/vulkan.c
src/detection/media.c
src/detection/datetime.c
src/detection/temps.c
src/detection/displayserver/displayServer.c
src/detection/displayserver/wayland.c
src/detection/displayserver/xcb.c
@@ -156,6 +195,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
@@ -164,6 +204,8 @@ 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)
@@ -265,12 +307,21 @@ if(ENABLE_XFCONF)
endif()
endif()
if(ENABLE_SQLITE3)
pkg_check_modules(SQLITE3 sqlite3)
if(SQLITE3_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_SQLITE3=1)
else()
message(WARNING "Package sqlite3 not found. Building without support.")
endif()
endif()
if(ENABLE_RPM)
pkg_check_modules(RPM rpm)
if(RPM_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_RPM=1)
else()
message(WARNING "Package librpm not found. Building without support.")
message(WARNING "Package rpm not found. Building without support.")
endif()
endif()
@@ -321,6 +372,55 @@ if(ENABLE_ZLIB)
endif()
endif()
if(ENABLE_CHAFA)
if(IMAGEMAGICK6_FOUND OR IMAGEMAGICK7_FOUND)
pkg_check_modules(CHAFA chafa>=1.10)
if(CHAFA_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CHAFA=1)
else()
message(WARNING "Package chafa>=1.10 not found. Building without support.")
endif()
else()
message(WARNING "Chafa not enabled, because neither ImageMagick6 nor ImageMagick7 were found. Building without support.")
endif()
endif()
if(ENABLE_EGL)
pkg_check_modules(EGL egl)
if(EGL_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EGL=1)
else()
message(WARNING "Package egl not found. Building without support.")
endif()
endif()
if(ENABLE_GLX)
pkg_check_modules(GLX glx)
if(GLX_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLX=1)
else()
message(WARNING "Package glx not found. Building without support.")
endif()
endif()
if(ENABLE_OSMESA)
pkg_check_modules(OSMESA osmesa)
if(OSMESA_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_OSMESA=1)
else()
message(WARNING "Package osmesa not found. Building without support.")
endif()
endif()
if(ENABLE_OPENCL)
pkg_check_modules(OPENCL OpenCL)
if(OPENCL_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_OPENCL=1)
else()
message(WARNING "Package opencl not found. Building without support.")
endif()
endif()
target_include_directories(libfastfetch
PUBLIC ${PROJECT_BINARY_DIR}
PUBLIC ${PROJECT_SOURCE_DIR}/src
@@ -336,10 +436,17 @@ target_include_directories(libfastfetch
PRIVATE ${DCONF_INCLUDE_DIRS}
PRIVATE ${DBUS_INCLUDE_DIRS}
PRIVATE ${XFCONF_INCLUDE_DIRS}
PRIVATE ${SQLITE3_INCLUDE_DIRS}
PRIVATE ${RPM_INCLUDE_DIRS}
PRIVATE ${IMAGEMAGICK7_INCLUDE_DIRS}
PRIVATE ${IMAGEMAGICK6_INCLUDE_DIRS}
PRIVATE ${ZLIB_INCLUDE_DIRS}
PRIVATE ${CHAFA_INCLUDE_DIRS}
PRIVATE ${VULKAN_INCLUDE_DIRS}
PRIVATE ${EGL_INCLUDE_DIRS}
PRIVATE ${GLX_INCLUDE_DIRS}
PRIVATE ${OSMESA_INCLUDE_DIRS}
PRIVATE ${OPENCL_INCLUDE_DIRS}
)
target_link_libraries(libfastfetch
@@ -347,7 +454,9 @@ target_link_libraries(libfastfetch
PRIVATE Threads::Threads
)
set_target_properties(libfastfetch PROPERTIES OUTPUT_NAME "fastfetch")
######################
# Executable targets #
######################
add_executable(fastfetch
src/fastfetch.c
@@ -363,16 +472,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
)
@@ -384,7 +488,9 @@ if (BUILD_TESTS)
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
endif()
# Installation
##################
# install target #
##################
include(GNUInstallDirs)
@@ -414,36 +520,23 @@ install(
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}
)
# Packaging
##################
# package target #
##################
set(CPACK_GENERATOR "DEB;RPM;TGZ;ZIP")
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_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
libmagickcore-6.q16hdri-6
libmagickcore-6.q16-6
")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
-4
View File
@@ -11,11 +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)
- [ ] 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
+33 -24
View File
@@ -19,32 +19,38 @@ There are some presets defined for fastfech in [`presets`](presets), you can can
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.
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
* [`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.
* [`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, Disk, Battery, Player, Song, 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, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, Ubuntu, Void, Zorin
Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Kubuntu, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, 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.
@@ -79,20 +85,23 @@ 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
Build: Follow the [build instructions](#building).
* Create DEB / RPM: Run `cmake --build . --target package`.
* Install directly: Run `sudo cmake --install . --prefix /usr/local`
## FAQ
+51 -1
View File
@@ -130,6 +130,8 @@ __fastfetch_completion()
"--localip-show-ipv4"
"--localip-show-ipv6"
"--localip-show-loop"
"--escape-bedrock"
"--pipe"
)
local FF_OPTIONS_STRING=(
@@ -152,6 +154,7 @@ __fastfetch_completion()
"-s"
"--structure"
"--set"
"--gl"
"--os-format"
"--os-key"
"--host-format"
@@ -216,6 +219,47 @@ __fastfetch_completion()
"--date-key"
"--time-format"
"--time-key"
"--vulkan-key"
"--vulkan-format"
"--opengl-key"
"--opengl-format"
"--opencl-key"
"--opencl-format"
"--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"
"--disk-error"
"--battery-error"
"--locale-error"
"--disk-error"
"--local-ip-error"
"--public-ip-error"
"--player-error"
"--song-error"
"--datetime-error"
"--date-error"
"--time-error"
"--vulkan-error"
"--opengl-error"
"--opencl-error"
)
local FF_OPTIONS_PATH=(
@@ -231,9 +275,15 @@ __fastfetch_completion()
"--lib-DConf"
"--lib-DBus"
"--lib-XFConf"
"--lib-RPM"
"--lib-sqlite3"
"--lib-rpm"
"--lib-imagemagick"
"--lib-z"
"--lib-chafa"
"--lib-egl"
"--lib-glx"
"--lib-osmesa"
"--lib-opencl"
"--battery-dir"
"--load-config"
)
+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:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Break:Colors
+6 -3
View File
@@ -1,7 +1,7 @@
--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: {}"
--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: {}"
@@ -17,12 +17,15 @@
--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-format "Name: {}; Pretty: {}; Vendor: {}; Logical online: {}; Logical configured: {}; Physical: {}; Cores: {}; temperature: {}; bios: {}; scaling max: {}; scaling min: {}; info max: {}; info min: {}; cpuinfo: {}; frequency: {}"
--cpu-usage-format "Percentage: {}"
--gpu-format "Vendor: {}; Vendor pretty: {}; Name: {}; Name pretty: {}; Driver: {}"
--gpu-format "Vendor: {}; Vendor pretty: {}; Name: {}; Name pretty: {}; Driver: {}; Temperature: {}"
--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: {}"
--vulkan-format "driver: {}; Api Version: {}; Conformance Version: {}"
--opengl-format "version: {}; renderer: {}; vendor: {}"
--opencl-format "version: {}; device: {}; vendor: {}"
+5
View File
@@ -1,4 +1,9 @@
#!/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 ..
+16 -17
View File
@@ -1,5 +1,7 @@
#include "fastfetch.h"
#include <stdlib.h>
#define FF_CACHE_VALUE_EXTENSION "ffcv"
#define FF_CACHE_SPLIT_EXTENSION "ffcs"
@@ -35,9 +37,6 @@ static void writeCacheFile(FFinstance* instance, const char* moduleName, const c
void ffCacheValidate(FFinstance* instance)
{
if(instance->config.recache)
return;
FFstrbuf content;
ffStrbufInit(&content);
readCacheFile(instance, "cacheversion", "ffv", &content);
@@ -80,7 +79,7 @@ void ffCacheClose(FFcache* cache)
fclose(cache->split);
}
static bool printCachedValue(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat)
static bool printCachedValue(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
@@ -98,7 +97,7 @@ static bool printCachedValue(FFinstance* instance, const char* moduleName, const
{
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
ffPrintLogoAndKey(instance, moduleName, moduleIndex, &moduleArgs->key);
puts(content.chars + startIndex);
startIndex = nullByteIndex + 1;
++moduleCounter;
@@ -109,7 +108,7 @@ static bool printCachedValue(FFinstance* instance, const char* moduleName, const
return moduleCounter > 1;
}
static bool printCachedFormat(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numArgs)
static bool printCachedFormat(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
@@ -137,7 +136,7 @@ static bool printCachedFormat(FFinstance* instance, const char* moduleName, cons
if(argumentCounter == numArgs)
{
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, NULL, numArgs, arguments);
ffPrintFormat(instance, moduleName, moduleIndex, moduleArgs, numArgs, arguments);
++moduleCounter;
argumentCounter = 0;
}
@@ -151,27 +150,27 @@ static bool printCachedFormat(FFinstance* instance, const char* moduleName, cons
return moduleCounter > 1;
}
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numArgs)
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs)
{
if(instance->config.recache)
return false;
if(formatString == NULL || formatString->length == 0)
return printCachedValue(instance, moduleName, customKeyFormat);
if(moduleArgs->outputFormat.length == 0)
return printCachedValue(instance, moduleName, moduleArgs);
else
return printCachedFormat(instance, moduleName, customKeyFormat, formatString, numArgs);
return printCachedFormat(instance, moduleName, moduleArgs, 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)
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(formatString == NULL || formatString->length == 0)
if(moduleArgs->outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
ffPrintLogoAndKey(instance, moduleName, moduleIndex, &moduleArgs->key);
ffStrbufPutTo(value, stdout);
}
else
{
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, NULL, numArgs, arguments);
ffPrintFormat(instance, moduleName, moduleIndex, moduleArgs, numArgs, arguments);
}
if(cache->value != NULL)
@@ -194,10 +193,10 @@ void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8
}
}
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* value, const FFstrbuf* formatString, 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)
{
FFcache cache;
ffCacheOpenWrite(instance, moduleName, &cache);
ffPrintAndAppendToCache(instance, moduleName, 0, customKeyFormat, &cache, value, formatString, numArgs, arguments);
ffPrintAndAppendToCache(instance, moduleName, 0, moduleArgs, &cache, value, numArgs, arguments);
ffCacheClose(&cache);
}
+2 -33
View File
@@ -32,15 +32,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;
@@ -72,6 +63,7 @@ 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 == *(double*)arg->value) || //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') ||
@@ -81,7 +73,7 @@ static inline bool formatArgSet(const FFformatarg* arg)
);
}
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 +120,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] == '-')
{
@@ -186,14 +171,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 +200,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
+95 -83
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
@@ -102,13 +103,21 @@ static void initState(FFstate* 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.logoSource);
instance->config.logoType = FF_LOGO_TYPE_AUTO;
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufInit(&instance->config.logoColors[i]);
instance->config.logoWidth = 65;
instance->config.logoWidth = 0;
instance->config.logoHeight = 0; //preserve aspect ratio
instance->config.logoPaddingLeft = 0;
instance->config.logoPaddingRight = 4;
instance->config.logoPrintRemaining = true;
@@ -123,69 +132,44 @@ static void defaultConfig(FFinstance* instance)
instance->config.allowSlowOperations = false;
instance->config.disableLinewrap = true;
instance->config.hideCursor = true;
instance->config.escapeBedrock = true;
instance->config.glType = FF_GL_TYPE_AUTO;
instance->config.pipe = false;
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.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);
@@ -198,9 +182,15 @@ 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);
ffStrbufInitA(&instance->config.diskFolders, 0);
@@ -225,29 +215,29 @@ void ffInitInstance(FFinstance* instance)
defaultConfig(instance);
}
static void resetConsole(bool disableLinewrap, bool hideCursor)
{
if(disableLinewrap)
fputs("\033[?7h", stdout);
if(hideCursor)
fputs("\033[?25h", stdout);
}
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;
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
struct sigaction action = {};
action.sa_handler = exitSignalHandler;
@@ -257,24 +247,28 @@ void ffStart(FFinstance* instance)
sigaction(SIGQUIT, &action, NULL);
//We do the cache validation here, so we can skip it if --recache is given
ffCacheValidate(instance);
if(!instance->config.recache)
ffCacheValidate(instance);
//reset everything to default before we start printing
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(instance->config.hideCursor)
if(ffHideCursor)
fputs("\033[?25l", stdout);
if(instance->config.disableLinewrap)
if(ffDisableLinewrap)
fputs("\033[?7l", stdout);
ffPrintLogo(instance);
ffLogoPrint(instance);
}
void ffFinish(FFinstance* instance)
{
ffPrintRemainingLogo(instance);
resetConsole(instance->config.disableLinewrap, instance->config.hideCursor);
if(instance->config.logoPrintRemaining)
ffLogoPrintRemaining(instance);
resetConsole();
}
//Must be in a file compiled with the libfastfetch target, because the FF_HAVE* macros are not defined for the executable targets
@@ -317,14 +311,32 @@ void ffListFeatures()
#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);
+27 -18
View File
@@ -1,11 +1,10 @@
#include "fastfetch.h"
#include <stdio.h>
#include <malloc.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <termios.h>
#include <poll.h>
bool ffWriteFDContent(int fd, const FFstrbuf* content)
{
@@ -61,7 +60,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);
}
@@ -128,32 +127,42 @@ bool ffFileExists(const char* fileName, mode_t mode)
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
}
void ffGetTerminalResponse(const char* request, char end, const char* format, ...)
void ffGetTerminalResponse(const char* request, const char* format, ...)
{
struct termios oldTerm, newTerm;
tcgetattr(STDIN_FILENO, &oldTerm);
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newTerm);
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];
int pos = 0;
while((size_t) pos < sizeof(buffer) - 1)
{
char c = (char) getc(stdin);
if(c == '\0')
break;
buffer[pos++] = c;
if(c == end)
break;
}
buffer[pos] = '\0';
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);
+1
View File
@@ -1,6 +1,7 @@
#include "fastfetch.h"
#include <stdarg.h>
#include <dlfcn.h>
static void* libraryLoad(const char* path, int maxVersion)
{
-1
View File
@@ -1,6 +1,5 @@
#include "fastfetch.h"
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
+26
View File
@@ -39,6 +39,32 @@ void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* mino
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);
}
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
+88 -24
View File
@@ -1,43 +1,49 @@
#include "fastfetch.h"
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...)
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
{
if(!instance->config.showErrors)
return;
ffLogoPrintLine(instance);
va_list arguments;
va_start(arguments, message);
if(formatString == NULL || formatString->length == 0)
if(!instance->config.pipe)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
vprintf(message, arguments);
puts(FASTFETCH_TEXT_MODIFIER_RESET);
fputs(FASTFETCH_TEXT_MODIFIER_RESET FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
ffPrintColor(&instance->config.mainColor);
}
//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
{
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);
FFstrbuf key;
ffStrbufInit(&key);
ffParseFormatString(&key, customKeyFormat, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
});
ffStrbufWriteTo(&key, stdout);
ffStrbufDestroy(&key);
}
va_end(arguments);
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* formatString, const FFstrbuf* error, uint32_t numArgs, const FFformatarg* arguments)
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, formatString, error, numArgs, arguments);
ffParseFormatString(&buffer, format, numArgs, arguments);
if(buffer.length > 0)
{
@@ -48,8 +54,66 @@ void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t m
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);
+1 -1
View File
@@ -1,6 +1,6 @@
#include "fastfetch.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
+23 -11
View File
@@ -1,5 +1,7 @@
#include "fastfetch.h"
#include <stdlib.h>
static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer)
{
if(**line == '\0')
@@ -90,24 +92,33 @@ bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
{
bool* searchedValues = malloc(sizeof(bool) * numQueries);
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((searchedValues[i] = queries[i].buffer->length == 0))
if((unsetValues[i] = queries[i].buffer->length == 0))
allSet = false;
}
if(allSet)
{
free(searchedValues);
return true;
}
FILE* file = fopen(filename, "r");
if(file == NULL)
return false;
if(allSet)
{
fclose(file);
if(unsetValues != valueStorage)
free(unsetValues);
return true;
}
char* line = NULL;
size_t len = 0;
@@ -115,7 +126,7 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
{
for(uint32_t i = 0; i < numQueries; i++)
{
if(!searchedValues[i])
if(!unsetValues[i])
continue;
uint32_t currentLength = queries[i].buffer->length;
@@ -125,13 +136,14 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
}
}
free(searchedValues);
if(line != NULL)
free(line);
fclose(file);
if(unsetValues != valueStorage)
free(unsetValues);
return true;
}
+70
View File
@@ -1,6 +1,8 @@
#include "fastfetch.h"
#include <pthread.h>
#include <string.h>
#include <dlfcn.h>
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
static dataObject data; \
@@ -267,6 +269,74 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
}
#endif //FF_HAVE_XFCONF
#ifdef FF_HAVE_SQLITE3
#include <sqlite3.h>
typedef struct SQLiteData
{
FF_LIBRARY_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_SYMBOL(sqlite3_prepare_v2)
FF_LIBRARY_SYMBOL(sqlite3_step)
FF_LIBRARY_SYMBOL(sqlite3_data_count)
FF_LIBRARY_SYMBOL(sqlite3_column_int)
FF_LIBRARY_SYMBOL(sqlite3_finalize)
FF_LIBRARY_SYMBOL(sqlite3_close)
} SQLiteData;
static const SQLiteData* getSQLiteData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3.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)
{
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) {
+70 -2
View File
@@ -61,16 +61,22 @@
# Logo type option:
# Sets the logo type to use.
# Must be auto, builtin, file, raw, sixel or kitty.
# Must be auto, builtin, file, raw, sixel, kitty or chafa.
# Default is auto.
#--logo-type auto
# Logo width option:
# Sets the width of the logos (in characters) if the logo is an image.
# Sets the width of the logo (in characters) if the logo is an image.
# Must be a positive integer.
# Default is 65.
#--logo-width 65
# Logo height option:
# Sets the height of the logo (in characters) if the logo is an image.
# Must be a positive integer.
# Default is 0 (keeps aspect ration).
#--logo-height 0
# Logo color options:
# Overwrite a color in the logo. Also works for user provided logos.
# In the user logo, they replace $[1-9]. Use $$ to print a single $ sign.
@@ -145,6 +151,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.
@@ -177,6 +195,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.
@@ -212,6 +233,47 @@
#--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
#--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.
@@ -227,6 +289,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
+23 -66
View File
@@ -18,11 +18,14 @@ General options:
--load-config <file>: load a config file or a preset (+)
--multithreading <?value>: use multiple threads to detect values
--allow-slow-operations <?value>: allow operations that are usually very slow for more detailed output
--escape-bedrock <?value>: on bedrock linux, sets if it should escape the bedrock jail or not
--pipe <?value>: disable logo and all escape sequences
Logo options:
-l,--logo <logo>: set the logo to use. The type is specified by --logo-type. If default: the name of a builtin logo or a path to a file
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel or kitty.
--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
@@ -30,6 +33,7 @@ Logo options:
--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>
@@ -42,71 +46,17 @@ Display options:
--disable-linewrap <?value>: weather to disable linewrap during the run
--hide-cursor <?value>: weather to hide the cursor during the run
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>
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.
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>
--<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>
@@ -120,9 +70,15 @@ 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:
--separator-string <str>: Set the string printed by the separator module
@@ -134,6 +90,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".
+3
View File
@@ -17,6 +17,8 @@ Locale
LocalIP
Memory
OS
OpenCL
OpenGL
Packages
Player
Processes
@@ -31,5 +33,6 @@ Theme
Time
Title
Uptime
Vulkan
WM
WMTheme
-1
View File
@@ -1,7 +1,6 @@
#include "fastfetch.h"
#include <time.h>
#include <pthread.h>
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
@@ -1,4 +1,5 @@
#include "displayServer.h"
#include <pthread.h>
#include <dirent.h>
+27 -28
View File
@@ -1,9 +1,12 @@
#include "displayServer.h"
#include <stdlib.h>
#include <string.h>
#ifdef FF_HAVE_WAYLAND
#include <wayland-client.h>
#include <pthread.h>
#include <dlfcn.h>
#include <wayland-client.h>
typedef struct WaylandData
{
@@ -73,32 +76,29 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
}
}
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result)
bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
{
if(getenv("XDG_RUNTIME_DIR") == NULL)
return;
FF_LIBRARY_LOAD(wayland, instance->config.libWayland, false, "libwayland-client.so", 1)
FF_LIBRARY_LOAD(wayland, instance->config.libWayland, , "libwayland-client.so", 1)
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,)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, 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_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,)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_marshal_constructor_versioned, wl_proxy_marshal_constructor_versioned, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_add_listener, wl_proxy_add_listener, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_output_interface, wl_output_interface, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_destroy, wl_proxy_destroy, false)
struct wl_display* display = ffwl_display_connect(NULL);
if(display == NULL)
{
dlclose(wayland);
return;
return false;
}
struct wl_registry* registry = (struct wl_registry*) ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
@@ -106,7 +106,7 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul
{
ffwl_display_disconnect(display);
dlclose(wayland);
return;
return false;
}
data.instance = instance;
@@ -133,20 +133,21 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul
//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;
}
#else
#endif
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;
#ifdef FF_HAVE_WAYLAND
if(detectWayland(instance, result))
return;
#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.
@@ -158,9 +159,7 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul
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.
//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);
}
#endif
+20 -4
View File
@@ -1,8 +1,11 @@
#include "displayServer.h"
#include <dirent.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 +43,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;
}
@@ -98,7 +106,15 @@ static void getKDE(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "plasmashell");
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
applyBetterWM(result, getenv("KDEWM"));
}
@@ -289,13 +305,13 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* result)
{
DIR* proc = opendir(FASTFETCH_TARGET_DIR_ROOT"/proc");
DIR* proc = opendir("/proc");
if(proc == NULL)
return;
FFstrbuf procPath;
ffStrbufInitA(&procPath, 64);
ffStrbufAppendS(&procPath, FASTFETCH_TARGET_DIR_ROOT"/proc/");
ffStrbufAppendS(&procPath, "/proc/");
uint32_t procPathLength = procPath.length;
+8 -6
View File
@@ -1,8 +1,10 @@
#include "displayServer.h"
#ifdef FF_HAVE_XCB
#include <xcb/xcb.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <xcb/xcb.h>
typedef struct XcbPropertyData
{
@@ -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");
@@ -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)
+6 -5
View File
@@ -1,6 +1,7 @@
#include "displayServer.h"
#ifdef FF_HAVE_X11
#include <dlfcn.h>
#include <X11/Xlib.h>
typedef struct X11PropertyData
@@ -34,7 +35,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");
@@ -161,15 +162,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)
+17 -53
View File
@@ -69,23 +69,14 @@ 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)
{
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);
@@ -146,41 +137,8 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
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);
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);
@@ -191,14 +149,20 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env
ffStrbufSet(&baseDirCopy, baseDir);
detectGTKFromConfigDir(&baseDirCopy, version, result);
if(allPropertiesSet(result))
break;
{
ffStrbufDestroy(&baseDirCopy);
return;
}
}
ffStrbufDestroy(&baseDirCopy);
ffStrbufDestroy(&buffer);
//Mate, Cinnamon and Gnome use dconf to save theme config
//On other DEs, this will do nothing
detectGTKFromDConf(instance, result);
}
#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 +177,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
+7 -2
View File
@@ -4,8 +4,10 @@
#include <pthread.h>
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#ifdef FF_HAVE_DBUS
#include <dlfcn.h>
#include <dbus/dbus.h>
#define FF_DBUS_ITER_CONTINUE(iterator) \
@@ -68,8 +70,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 +88,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;
+82 -4
View File
@@ -1,15 +1,17 @@
#include "fastfetch.h"
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#if !defined(__ANDROID__)
static void parseFile(const char* fileName, FFOSResult* result)
static bool parseFile(const char* fileName, FFOSResult* result)
{
if(result->name.length > 0 && result->prettyName.length > 0)
return;
if(result->id.length > 0 && result->name.length > 0 && result->prettyName.length > 0)
return true;
ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
return ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
{"NAME =", &result->name},
{"DISTRIB_DESCRIPTION =", &result->prettyName},
{"PRETTY_NAME =", &result->prettyName},
@@ -26,6 +28,67 @@ static void parseFile(const char* fileName, FFOSResult* result)
});
}
static void getUbuntuFlavour(FFOSResult* result)
{
const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
if(!ffStrSet(xdgConfigDirs))
return;
if(strstr(xdgConfigDirs, "kde") != NULL || strstr(xdgConfigDirs, "plasma") != NULL)
{
ffStrbufSetS(&result->name, "Kubuntu");
ffStrbufSetS(&result->prettyName, "Kubuntu");
ffStrbufSetS(&result->id, "kubuntu");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "xfce") != NULL || strstr(xdgConfigDirs, "xubuntu") != NULL)
{
ffStrbufSetS(&result->name, "Xubuntu");
ffStrbufSetS(&result->prettyName, "Xubuntu");
ffStrbufSetS(&result->id, "xubuntu");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "lxde") != NULL || strstr(xdgConfigDirs, "lubuntu") != NULL)
{
ffStrbufSetS(&result->name, "Lubuntu");
ffStrbufSetS(&result->prettyName, "Lubuntu");
ffStrbufSetS(&result->id, "lubuntu");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "budgie") != NULL)
{
ffStrbufSetS(&result->name, "Ubuntu Budgie");
ffStrbufSetS(&result->prettyName, "Ubuntu Budgie");
ffStrbufSetS(&result->id, "ubuntu-budgie");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "mate") != NULL)
{
ffStrbufSetS(&result->name, "Ubuntu MATE");
ffStrbufSetS(&result->prettyName, "Ubuntu MATE");
ffStrbufSetS(&result->id, "ubuntu-mate");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "studio") != NULL)
{
ffStrbufSetS(&result->name, "Ubuntu Studio");
ffStrbufSetS(&result->prettyName, "Ubuntu Studio");
ffStrbufSetS(&result->id, "ubuntu-studio");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
}
#endif
const FFOSResult* ffDetectOS(const FFinstance* instance)
@@ -62,12 +125,27 @@ const FFOSResult* ffDetectOS(const FFinstance* instance)
{
parseFile(instance->config.osFile.chars, &result);
}
else if(instance->config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock/etc/bedrock-release", &result))
{
if(result.id.length == 0)
ffStrbufAppendS(&result.id, "bedrock");
if(result.name.length == 0)
ffStrbufAppendS(&result.name, "Bedrock");
if(result.prettyName.length == 0)
ffStrbufAppendS(&result.prettyName, "Bedrock Linux");
}
else
{
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/os-release", &result);
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", &result);
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/lsb-release", &result);
}
if(ffStrbufIgnCaseCompS(&result.id, "ubuntu") == 0)
getUbuntuFlavour(&result);
#else
ffStrbufSetS(&result.name, "Android");
ffStrbufSetS(&result.id, "android");
+1
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
+22 -15
View File
@@ -1,16 +1,13 @@
#include "fastfetch.h"
#include <string.h>
#include <pthread.h>
#include <dirent.h>
#include <string.h>
static bool isTempFile(const char* name)
{
return
name[0] == 't' &&
name[1] == 'e' &&
name[2] == 'm' &&
name[3] == 'p' &&
strncmp(name, "temp", 4) == 0 &&
name[4] >= '0' &&
name[4] <= '9' &&
strncmp(name + 5, "_input", 6) == 0;
@@ -23,22 +20,34 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value)
return false;
uint32_t dirLength = dir->length;
value->value = 0.0 / 0.0; //use NaN as error value
FFstrbuf valueString;
ffStrbufInit(&valueString);
struct dirent* dirent;
while((dirent = readdir(dirp)) != NULL)
{
if(isTempFile(dirent->d_name))
{
ffStrbufAppendS(dir, dirent->d_name);
ffGetFileContent(dir->chars, &value->value);
ffStrbufSubstrBefore(dir, dirLength);
break;
}
if(!isTempFile(dirent->d_name))
continue;
ffStrbufAppendS(dir, dirent->d_name);
ffGetFileContent(dir->chars, &valueString);
ffStrbufSubstrBefore(dir, dirLength);
//ffStrbufToDouble() returns NaN if the string couldn't be parsed
value->value = ffStrbufToDouble(&valueString);
if(value->value != value->value)
continue;
value->value /= 1000.0; //millidegrees to degrees
break;
}
closedir(dirp);
ffStrbufDestroy(&valueString);
if(value->value.length == 0)
if(value->value != value->value)
return false;
ffStrbufAppendS(dir, "name");
@@ -95,12 +104,10 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance)
FFTempValue* temp = ffListAdd(&result.values);
ffStrbufInit(&temp->name);
ffStrbufInit(&temp->deviceClass);
ffStrbufInit(&temp->value);
if(!parseHwmonDir(&baseDir, temp))
{
ffStrbufDestroy(&temp->name);
ffStrbufDestroy(&temp->deviceClass);
ffStrbufDestroy(&temp->value);
--result.values.length;
}
+14 -4
View File
@@ -2,6 +2,7 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
@@ -16,7 +17,7 @@ static void getProcessInformation(const char* pid, FFstrbuf* processName, FFstrb
{
FFstrbuf cmdlineFilePath;
ffStrbufInit(&cmdlineFilePath);
ffStrbufAppendS(&cmdlineFilePath, FASTFETCH_TARGET_DIR_ROOT"/proc/");
ffStrbufAppendS(&cmdlineFilePath, "/proc/");
ffStrbufAppendS(&cmdlineFilePath, pid);
ffStrbufAppendS(&cmdlineFilePath, "/cmdline");
@@ -36,7 +37,7 @@ static void getTerminalShell(FFTerminalShellResult* result, const char* pid)
{
FFstrbuf statFilePath;
ffStrbufInit(&statFilePath);
ffStrbufAppendS(&statFilePath, FASTFETCH_TARGET_DIR_ROOT"/proc/");
ffStrbufAppendS(&statFilePath, "/proc/");
ffStrbufAppendS(&statFilePath, pid);
ffStrbufAppendS(&statFilePath, "/stat");
@@ -119,8 +120,17 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
term = getenv("SSH_TTY");
//Windows Terminal
if(!ffStrSet(term) && getenv("WT_SESSION") != NULL)
term = "Windows Terminal";
if(!ffStrSet(term) && (
getenv("WT_SESSION") != NULL ||
getenv("WT_PROFILE_ID") != NULL
)) term = "Windows Terminal";
//Termux
if(!ffStrSet(term) && (
getenv("TERMUX_VERSION") != NULL ||
getenv("TERMUX_MAIN_PACKAGE_FORMAT") != NULL ||
getenv("TMUX_TMPDIR") != NULL
)) term = "Termux";
//Normal Terminal
if(!ffStrSet(term))
+228
View File
@@ -0,0 +1,228 @@
#include "fastfetch.h"
#include <pthread.h>
#ifdef FF_HAVE_VULKAN
#include <stdlib.h>
#include <dlfcn.h>
#include <vulkan/vulkan.h>
static inline void applyVulkanVersion(uint32_t vulkanVersion, FFVersion* ffVersion)
{
ffVersion->major = VK_VERSION_MAJOR(vulkanVersion);
ffVersion->minor = VK_VERSION_MINOR(vulkanVersion);
ffVersion->patch = VK_VERSION_PATCH(vulkanVersion);
}
static void applyDriverName(VkPhysicalDeviceDriverProperties* properties, FFstrbuf* result)
{
if(!ffStrSet(properties->driverName))
return;
ffStrbufAppendS(result, properties->driverName);
if(!ffStrSet(properties->driverInfo))
return;
ffStrbufAppendS(result, " [");
ffStrbufAppendS(result, properties->driverInfo);
ffStrbufAppendC(result, ']');
}
static void detectVulkan(const FFinstance* instance, FFVulkanResult* result)
{
FF_LIBRARY_LOAD(vulkan, instance->config.libVulkan, , "libvulkan.so", 2)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetInstanceProcAddr,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkCreateInstance,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkDestroyInstance,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkEnumeratePhysicalDevices,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetPhysicalDeviceProperties,)
//Some drivers (nvdc) print messages to stdout
//and thats the best way i found to disable that
ffSuppressIO(true);
FFVersion instanceVersion = FF_VERSION_INIT;
//We need to get the function pointer this way, because it is only provided by vulkan 1.1 and higher.
//a dlsym would fail on 1.0 implementations
PFN_vkEnumerateInstanceVersion ffvkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) ffvkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
if(ffvkEnumerateInstanceVersion != NULL)
{
uint32_t version;
if(ffvkEnumerateInstanceVersion(&version) == VK_SUCCESS)
applyVulkanVersion(version, &instanceVersion);
}
const uint32_t projectVersion = VK_MAKE_VERSION(
FASTFETCH_PROJECT_VERSION_MAJOR,
FASTFETCH_PROJECT_VERSION_MINOR,
FASTFETCH_PROJECT_VERSION_PATCH
);
//We need to request 1.2 to get physicalDeviceDriverProperties
uint32_t requestedVkVersion = VK_API_VERSION_1_0;
if(instanceVersion.minor >= 2)
requestedVkVersion = VK_API_VERSION_1_2;
const VkApplicationInfo applicationInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = FASTFETCH_PROJECT_NAME,
.applicationVersion = projectVersion,
.pEngineName = "vulkanPrintGPUs",
.engineVersion = projectVersion,
.apiVersion = requestedVkVersion
};
const VkInstanceCreateInfo instanceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = NULL,
.pApplicationInfo = &applicationInfo,
.enabledLayerCount = 0,
.ppEnabledLayerNames = NULL,
.enabledExtensionCount = 0,
.ppEnabledExtensionNames = NULL,
.flags = 0
};
VkInstance vkInstance;
if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS)
{
dlclose(vulkan);
ffSuppressIO(false);
return;
}
//if instance creation succeeded, but vkEnumerateInstanceVersion didn't, this means we are running against a vulkan 1.0 implementation
//explicitly set this version, if no device is found, so we still have at least this info
if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0)
instanceVersion.major = 1;
uint32_t physicalDeviceCount;
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
{
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return;
}
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
{
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return;
}
PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2");
FFVersion maxDeviceApiVersion = FF_VERSION_INIT;
FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT;
for(uint32_t i = 0; i < physicalDeviceCount; i++)
{
//Get device properties.
//On VK 1.2 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain.
//This is required to get the driver name and conformance version.
VkPhysicalDeviceDriverProperties driverProperties;
driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
driverProperties.pNext = NULL;
driverProperties.driverName[0] = '\0';
driverProperties.conformanceVersion = (VkConformanceVersion) {0, 0, 0, 0};
VkPhysicalDeviceProperties2 physicalDeviceProperties;
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physicalDeviceProperties.pNext = &driverProperties;
if(ffvkGetPhysicalDeviceProperties2 != NULL)
ffvkGetPhysicalDeviceProperties2(physicalDevices[i], &physicalDeviceProperties);
else
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties.properties);
//If the device api version is higher than the current highest device api version, overwrite it
//In this case, also use the current device driver name as the shown driver name
FFVersion deviceAPIVersion = FF_VERSION_INIT;
applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion);
if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0)
{
maxDeviceApiVersion = deviceAPIVersion;
applyDriverName(&driverProperties, &result->driver);
}
//If the device conformance version is higher than the current highest device conformance version, overwrite it
FFVersion deviceConformanceVersion = FF_VERSION_INIT;
deviceConformanceVersion.major = driverProperties.conformanceVersion.major;
deviceConformanceVersion.minor = driverProperties.conformanceVersion.minor;
deviceConformanceVersion.patch = driverProperties.conformanceVersion.patch;
if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0)
maxDeviceConformanceVersion = deviceConformanceVersion;
//Add the device to the list of devices shown by the GPU module
//We don't want softare rasterizers to show up as physical gpu
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
continue;
FFGPUResult* gpu = ffListAdd(&result->devices);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
gpu->temperature = 0.0 / 0.0; //NaN, no way to detect temperature using vulkan
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
}
//If the highest device version is lower than the instance version, use it as our vulkan version
//otherwise the instance version is the vulkan version
if(ffVersionCompare(&instanceVersion, &maxDeviceApiVersion) > 0)
ffVersionToPretty(&maxDeviceApiVersion, &result->apiVersion);
else
ffVersionToPretty(&instanceVersion, &result->apiVersion);
//Use the highest device conformace version as our conformance version
ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion);
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
}
#endif
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance)
{
static FFVulkanResult 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.driver);
ffStrbufInit(&result.apiVersion);
ffStrbufInit(&result.conformanceVersion);
ffListInit(&result.devices, sizeof(FFGPUResult));
#ifdef FF_HAVE_VULKAN
detectVulkan(instance, &result);
#else
FF_UNUSED(instance);
#endif
pthread_mutex_unlock(&mutex);
return &result;
}
+287 -106
View File
@@ -1,11 +1,9 @@
#include "fastfetch.h"
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
// Things only needed by fastfetch
typedef struct FFdata
@@ -28,7 +26,7 @@ static void constructAndPrintCommandHelpFormat(const char* name, const char* def
for(uint32_t i = 1; i <= numArgs; i++)
printf(" {%u}: %s\n", i, va_arg(argp, const char*));
printf("The default is something like \"%s\".\n", def);
printf("The default is something similar to \"%s\".\n", def);
va_end(argp);
}
@@ -62,10 +60,22 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "host-format") == 0)
{
constructAndPrintCommandHelpFormat("host", "{2} {3}", 3,
"Host family",
"Host name",
"Host version"
constructAndPrintCommandHelpFormat("host", "{2} {3}", 15,
"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"
);
}
else if(strcasecmp(command, "kernel-format") == 0)
@@ -93,7 +103,7 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "packages-format") == 0)
{
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xps), {8}, (flatpak), {9} (snap)", 9,
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-user), {9} (nix-default), {10} (flatpak), {11} (snap)", 11,
"Number of all packages",
"Number of pacman packages",
"Pacman branch on manjaro",
@@ -101,6 +111,8 @@ static inline void printCommandHelp(const char* command)
"Number of rpm packages",
"Number of emerge packages",
"Number of xbps packages",
"Number of nix-user packages",
"Number of nix-default packages",
"Number of flatpak packages",
"Number of snap packages"
);
@@ -222,7 +234,7 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "cpu-format") == 0)
{
constructAndPrintCommandHelpFormat("cpu", "{2} ({7}) @ {14}GHz", 14,
constructAndPrintCommandHelpFormat("cpu", "{2} ({7}) @ {15}GHz", 15,
"CPU name",
"Prettified CPU name",
"CPU Vendor name (Vendor ID)",
@@ -230,6 +242,7 @@ static inline void printCommandHelp(const char* command)
"CPU logical core count configured",
"CPU physical core count",
"Always set core count",
"CPU package temperature",
"frequency bios limit",
"frequency scaling max",
"frequency scaling min",
@@ -247,12 +260,13 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "gpu-format") == 0)
{
constructAndPrintCommandHelpFormat("gpu", "{2} {4}", 5,
constructAndPrintCommandHelpFormat("gpu", "{2} {4}", 6,
"GPU vendor",
"GPU vendor pretty",
"GPU name",
"GPU name pretty",
"GPU driver"
"GPU driver",
"GPU temperature"
);
}
else if(strcasecmp(command, "memory-format") == 0)
@@ -265,7 +279,7 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "disk-format") == 0)
{
constructAndPrintCommandHelpFormat("disk", "{}GB / {}GB ({4}%)", 4,
constructAndPrintCommandHelpFormat("disk", "{}GiB / {}GiB ({4}%)", 4,
"Used disk space",
"Total disk space",
"Number of files",
@@ -334,7 +348,7 @@ static inline void printCommandHelp(const char* command)
"day in month",
"day in Week",
"hour",
"hout with leading zero",
"hour with leading zero",
"hour 12h format",
"hour 12h format with leading zero",
"minute",
@@ -343,6 +357,31 @@ static inline void printCommandHelp(const char* command)
"second with leading zero"
);
}
else if(strcasecmp(command, "vulkan-format") == 0)
{
constructAndPrintCommandHelpFormat("vulkan", "{} (driver), {} (api version)", 3,
"Driver name",
"API version",
"Conformance version"
);
}
else if(strcasecmp(command, "opengl-format") == 0)
{
constructAndPrintCommandHelpFormat("opengl", "{}", 3,
"version",
"renderer",
"vendor",
"shading language version"
);
}
else if(strcasecmp(command, "opencl-format") == 0)
{
constructAndPrintCommandHelpFormat("opencl", "{}", 3,
"version",
"device",
"vendor"
);
}
else
fprintf(stderr, "No specific help for command %s provided\n", command);
}
@@ -673,17 +712,17 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
}
else if(strcasecmp(key, "--list-logos") == 0)
{
ffListBuiltinLogos();
ffLogoBuiltinList();
exit(0);
}
else if(strcasecmp(key, "--list-logos-autocompletion") == 0)
{
ffListBuiltinLogosAutocompletion();
ffLogoBuiltinListAutocompletion();
exit(0);
}
else if(strcasecmp(key, "--print-logos") == 0)
{
ffPrintBuiltinLogos(instance);
ffLogoBuiltinPrint(instance);
exit(0);
}
@@ -708,13 +747,26 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
data->multithreading = optionParseBoolean(value);
else if(strcasecmp(key, "--allow-slow-operations") == 0)
instance->config.allowSlowOperations = optionParseBoolean(value);
else if(strcasecmp(key, "--escape-bedrock") == 0)
instance->config.escapeBedrock = optionParseBoolean(value);
else if(strcasecmp(key, "--pipe") == 0)
instance->config.pipe = optionParseBoolean(value);
////////////////
//Logo options//
////////////////
else if(strcasecmp(key, "-l") == 0 || strcasecmp(key, "--logo") == 0)
{
optionParseString(key, value, &instance->config.logoSource);
//this is usally wanted when using the none logo
if(strcasecmp(value, "none") == 0)
{
instance->config.logoPaddingRight = 0;
instance->config.logoPaddingLeft = 0;
}
}
else if(strcasecmp(key, "--logo-type") == 0)
{
if(value == NULL)
@@ -735,6 +787,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
instance->config.logoType = FF_LOGO_TYPE_SIXEL;
else if(strcasecmp(value, "kitty") == 0)
instance->config.logoType = FF_LOGO_TYPE_KITTY;
else if(strcasecmp(value, "chafa") == 0)
instance->config.logoType = FF_LOGO_TYPE_CHAFA;
else
{
fprintf(stderr, "Error: unknown logo type: %s\n", value);
@@ -757,6 +811,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
}
else if(strcasecmp(key, "--logo-width") == 0)
instance->config.logoWidth = optionParseUInt32(key, value);
else if(strcasecmp(key, "--logo-height") == 0)
instance->config.logoHeight = optionParseUInt32(key, value);
else if(strcasecmp(key, "--logo-padding") == 0)
{
uint32_t padding = optionParseUInt32(key, value);
@@ -789,6 +845,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.logoSource);
instance->config.logoType = FF_LOGO_TYPE_RAW;
}
else if(strcasecmp(key, "--chafa") == 0)
{
optionParseString(key, value, &instance->config.logoSource);
instance->config.logoType = FF_LOGO_TYPE_CHAFA;
}
///////////////////
//Display options//
@@ -827,134 +888,214 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
ffValuestoreSet(&data->valuestore, value, separator + 1);
}
////////////////////////
//Format + Key options//
////////////////////////
////////////////////////////////
//Format + Key + Error options//
////////////////////////////////
else if(strcasecmp(key, "--os-format") == 0)
optionParseString(key, value, &instance->config.osFormat);
else if(strcasecmp(key, "--os-key") == 0)
optionParseString(key, value, &instance->config.osKey);
else if(strcasecmp(key, "--host-format") == 0)
optionParseString(key, value, &instance->config.hostFormat);
optionParseString(key, value, &instance->config.os.key);
else if(strcasecmp(key, "--os-format") == 0)
optionParseString(key, value, &instance->config.os.outputFormat);
else if(strcasecmp(key, "--os-error") == 0)
optionParseString(key, value, &instance->config.os.errorFormat);
else if(strcasecmp(key, "--host-key") == 0)
optionParseString(key, value, &instance->config.hostKey);
else if(strcasecmp(key, "--kernel-format") == 0)
optionParseString(key, value, &instance->config.kernelFormat);
optionParseString(key, value, &instance->config.host.key);
else if(strcasecmp(key, "--host-format") == 0)
optionParseString(key, value, &instance->config.host.outputFormat);
else if(strcasecmp(key, "--host-error") == 0)
optionParseString(key, value, &instance->config.host.errorFormat);
else if(strcasecmp(key, "--kernel-key") == 0)
optionParseString(key, value, &instance->config.kernelKey);
else if(strcasecmp(key, "--uptime-format") == 0)
optionParseString(key, value, &instance->config.uptimeFormat);
optionParseString(key, value, &instance->config.kernel.key);
else if(strcasecmp(key, "--kernel-format") == 0)
optionParseString(key, value, &instance->config.kernel.outputFormat);
else if(strcasecmp(key, "--kernel-error") == 0)
optionParseString(key, value, &instance->config.kernel.errorFormat);
else if(strcasecmp(key, "--uptime-key") == 0)
optionParseString(key, value, &instance->config.uptimeKey);
else if(strcasecmp(key, "--processes-format") == 0)
optionParseString(key, value, &instance->config.processesFormat);
optionParseString(key, value, &instance->config.uptime.key);
else if(strcasecmp(key, "--uptime-format") == 0)
optionParseString(key, value, &instance->config.uptime.outputFormat);
else if(strcasecmp(key, "--uptime-error") == 0)
optionParseString(key, value, &instance->config.uptime.errorFormat);
else if(strcasecmp(key, "--processes-key") == 0)
optionParseString(key, value, &instance->config.processesKey);
else if(strcasecmp(key, "--packages-format") == 0)
optionParseString(key, value, &instance->config.packagesFormat);
optionParseString(key, value, &instance->config.processes.key);
else if(strcasecmp(key, "--processes-format") == 0)
optionParseString(key, value, &instance->config.processes.outputFormat);
else if(strcasecmp(key, "--processes-error") == 0)
optionParseString(key, value, &instance->config.processes.errorFormat);
else if(strcasecmp(key, "--packages-key") == 0)
optionParseString(key, value, &instance->config.packagesKey);
else if(strcasecmp(key, "--shell-format") == 0)
optionParseString(key, value, &instance->config.shellFormat);
optionParseString(key, value, &instance->config.packages.key);
else if(strcasecmp(key, "--packages-format") == 0)
optionParseString(key, value, &instance->config.packages.outputFormat);
else if(strcasecmp(key, "--packages-error") == 0)
optionParseString(key, value, &instance->config.packages.errorFormat);
else if(strcasecmp(key, "--shell-key") == 0)
optionParseString(key, value, &instance->config.shellKey);
else if(strcasecmp(key, "--resolution-format") == 0)
optionParseString(key, value, &instance->config.resolutionFormat);
optionParseString(key, value, &instance->config.shell.key);
else if(strcasecmp(key, "--shell-format") == 0)
optionParseString(key, value, &instance->config.shell.outputFormat);
else if(strcasecmp(key, "--shell-error") == 0)
optionParseString(key, value, &instance->config.shell.errorFormat);
else if(strcasecmp(key, "--resolution-key") == 0)
optionParseString(key, value, &instance->config.resolutionKey);
else if(strcasecmp(key, "--de-format") == 0)
optionParseString(key, value, &instance->config.deFormat);
optionParseString(key, value, &instance->config.resolution.key);
else if(strcasecmp(key, "--resolution-format") == 0)
optionParseString(key, value, &instance->config.resolution.outputFormat);
else if(strcasecmp(key, "--resolution-error") == 0)
optionParseString(key, value, &instance->config.resolution.errorFormat);
else if(strcasecmp(key, "--de-key") == 0)
optionParseString(key, value, &instance->config.deKey);
else if(strcasecmp(key, "--wm-format") == 0)
optionParseString(key, value, &instance->config.wmFormat);
optionParseString(key, value, &instance->config.de.key);
else if(strcasecmp(key, "--de-format") == 0)
optionParseString(key, value, &instance->config.de.outputFormat);
else if(strcasecmp(key, "--de-error") == 0)
optionParseString(key, value, &instance->config.de.errorFormat);
else if(strcasecmp(key, "--wm-key") == 0)
optionParseString(key, value, &instance->config.wmKey);
else if(strcasecmp(key, "--wm-theme-format") == 0)
optionParseString(key, value, &instance->config.wmThemeFormat);
optionParseString(key, value, &instance->config.wm.key);
else if(strcasecmp(key, "--wm-format") == 0)
optionParseString(key, value, &instance->config.wm.outputFormat);
else if(strcasecmp(key, "--wm-error") == 0)
optionParseString(key, value, &instance->config.wm.errorFormat);
else if(strcasecmp(key, "--wm-theme-key") == 0)
optionParseString(key, value, &instance->config.wmThemeKey);
else if(strcasecmp(key, "--theme-format") == 0)
optionParseString(key, value, &instance->config.themeFormat);
optionParseString(key, value, &instance->config.wmTheme.key);
else if(strcasecmp(key, "--wm-theme-format") == 0)
optionParseString(key, value, &instance->config.wmTheme.outputFormat);
else if(strcasecmp(key, "--wm-theme-error") == 0)
optionParseString(key, value, &instance->config.wmTheme.errorFormat);
else if(strcasecmp(key, "--theme-key") == 0)
optionParseString(key, value, &instance->config.themeKey);
else if(strcasecmp(key, "--icons-format") == 0)
optionParseString(key, value, &instance->config.iconsFormat);
optionParseString(key, value, &instance->config.theme.key);
else if(strcasecmp(key, "--theme-format") == 0)
optionParseString(key, value, &instance->config.theme.outputFormat);
else if(strcasecmp(key, "--theme-error") == 0)
optionParseString(key, value, &instance->config.theme.errorFormat);
else if(strcasecmp(key, "--icons-key") == 0)
optionParseString(key, value, &instance->config.iconsKey);
else if(strcasecmp(key, "--font-format") == 0)
optionParseString(key, value, &instance->config.fontFormat);
optionParseString(key, value, &instance->config.icons.key);
else if(strcasecmp(key, "--icons-format") == 0)
optionParseString(key, value, &instance->config.icons.outputFormat);
else if(strcasecmp(key, "--icons-error") == 0)
optionParseString(key, value, &instance->config.icons.errorFormat);
else if(strcasecmp(key, "--font-key") == 0)
optionParseString(key, value, &instance->config.fontKey);
optionParseString(key, value, &instance->config.font.key);
else if(strcasecmp(key, "--font-format") == 0)
optionParseString(key, value, &instance->config.font.outputFormat);
else if(strcasecmp(key, "--font-error") == 0)
optionParseString(key, value, &instance->config.font.errorFormat);
else if(strcasecmp(key, "--cursor-key") == 0)
optionParseString(key, value, &instance->config.cursorKey);
optionParseString(key, value, &instance->config.cursor.key);
else if(strcasecmp(key, "--cursor-format") == 0)
optionParseString(key, value, &instance->config.cursorFormat);
else if(strcasecmp(key, "--terminal-format") == 0)
optionParseString(key, value, &instance->config.terminalFormat);
optionParseString(key, value, &instance->config.cursor.outputFormat);
else if(strcasecmp(key, "--cursor-error") == 0)
optionParseString(key, value, &instance->config.cursor.errorFormat);
else if(strcasecmp(key, "--terminal-key") == 0)
optionParseString(key, value, &instance->config.terminalKey);
else if(strcasecmp(key, "--terminal-font-format") == 0)
optionParseString(key, value, &instance->config.termFontFormat);
optionParseString(key, value, &instance->config.terminal.key);
else if(strcasecmp(key, "--terminal-format") == 0)
optionParseString(key, value, &instance->config.terminal.outputFormat);
else if(strcasecmp(key, "--terminal-error") == 0)
optionParseString(key, value, &instance->config.terminal.errorFormat);
else if(strcasecmp(key, "--terminal-font-key") == 0)
optionParseString(key, value, &instance->config.termFontKey);
else if(strcasecmp(key, "--cpu-format") == 0)
optionParseString(key, value, &instance->config.cpuFormat);
else if(strcasecmp(key, "--cpu-usage-format") == 0)
optionParseString(key, value, &instance->config.cpuUsageFormat);
optionParseString(key, value, &instance->config.terminalFont.key);
else if(strcasecmp(key, "--terminal-font-format") == 0)
optionParseString(key, value, &instance->config.terminalFont.outputFormat);
else if(strcasecmp(key, "--terminal-font-error") == 0)
optionParseString(key, value, &instance->config.terminalFont.errorFormat);
else if(strcasecmp(key, "--cpu-key") == 0)
optionParseString(key, value, &instance->config.cpuKey);
optionParseString(key, value, &instance->config.cpu.key);
else if(strcasecmp(key, "--cpu-format") == 0)
optionParseString(key, value, &instance->config.cpu.outputFormat);
else if(strcasecmp(key, "--cpu-error") == 0)
optionParseString(key, value, &instance->config.cpu.errorFormat);
else if(strcasecmp(key, "--cpu-usage-key") == 0)
optionParseString(key, value, &instance->config.cpuUsageKey);
else if(strcasecmp(key, "--gpu-format") == 0)
optionParseString(key, value, &instance->config.gpuFormat);
optionParseString(key, value, &instance->config.cpuUsage.key);
else if(strcasecmp(key, "--cpu-usage-format") == 0)
optionParseString(key, value, &instance->config.cpuUsage.outputFormat);
else if(strcasecmp(key, "--cpu-usage-error") == 0)
optionParseString(key, value, &instance->config.cpuUsage.errorFormat);
else if(strcasecmp(key, "--gpu-key") == 0)
optionParseString(key, value, &instance->config.gpuKey);
else if(strcasecmp(key, "--memory-format") == 0)
optionParseString(key, value, &instance->config.memoryFormat);
optionParseString(key, value, &instance->config.gpu.key);
else if(strcasecmp(key, "--gpu-format") == 0)
optionParseString(key, value, &instance->config.gpu.outputFormat);
else if(strcasecmp(key, "--gpu-error") == 0)
optionParseString(key, value, &instance->config.gpu.errorFormat);
else if(strcasecmp(key, "--memory-key") == 0)
optionParseString(key, value, &instance->config.memoryKey);
else if(strcasecmp(key, "--disk-format") == 0)
optionParseString(key, value, &instance->config.diskFormat);
optionParseString(key, value, &instance->config.memory.key);
else if(strcasecmp(key, "--memory-format") == 0)
optionParseString(key, value, &instance->config.memory.outputFormat);
else if(strcasecmp(key, "--memory-error") == 0)
optionParseString(key, value, &instance->config.memory.errorFormat);
else if(strcasecmp(key, "--disk-key") == 0)
optionParseString(key, value, &instance->config.diskKey);
else if(strcasecmp(key, "--battery-format") == 0)
optionParseString(key, value, &instance->config.batteryFormat);
optionParseString(key, value, &instance->config.disk.key);
else if(strcasecmp(key, "--disk-format") == 0)
optionParseString(key, value, &instance->config.disk.outputFormat);
else if(strcasecmp(key, "--disk-error") == 0)
optionParseString(key, value, &instance->config.disk.errorFormat);
else if(strcasecmp(key, "--battery-key") == 0)
optionParseString(key, value, &instance->config.batteryKey);
else if(strcasecmp(key, "--locale-format") == 0)
optionParseString(key, value, &instance->config.localeFormat);
optionParseString(key, value, &instance->config.battery.key);
else if(strcasecmp(key, "--battery-format") == 0)
optionParseString(key, value, &instance->config.battery.outputFormat);
else if(strcasecmp(key, "--battery-error") == 0)
optionParseString(key, value, &instance->config.battery.errorFormat);
else if(strcasecmp(key, "--locale-key") == 0)
optionParseString(key, value, &instance->config.localeKey);
optionParseString(key, value, &instance->config.locale.key);
else if(strcasecmp(key, "--locale-format") == 0)
optionParseString(key, value, &instance->config.locale.outputFormat);
else if(strcasecmp(key, "--locale-error") == 0)
optionParseString(key, value, &instance->config.locale.errorFormat);
else if(strcasecmp(key, "--local-ip-key") == 0)
optionParseString(key, value, &instance->config.localIpKey);
optionParseString(key, value, &instance->config.localIP.key);
else if(strcasecmp(key, "--local-ip-format") == 0)
optionParseString(key, value, &instance->config.localIpFormat);
optionParseString(key, value, &instance->config.localIP.outputFormat);
else if(strcasecmp(key, "--local-ip-error") == 0)
optionParseString(key, value, &instance->config.localIP.errorFormat);
else if(strcasecmp(key, "--public-ip-key") == 0)
optionParseString(key, value, &instance->config.publicIpKey);
optionParseString(key, value, &instance->config.publicIP.key);
else if(strcasecmp(key, "--public-ip-format") == 0)
optionParseString(key, value, &instance->config.publicIpFormat);
optionParseString(key, value, &instance->config.publicIP.outputFormat);
else if(strcasecmp(key, "--public-ip-error") == 0)
optionParseString(key, value, &instance->config.publicIP.errorFormat);
else if(strcasecmp(key, "--player-key") == 0)
optionParseString(key, value, &instance->config.playerKey);
optionParseString(key, value, &instance->config.player.key);
else if(strcasecmp(key, "--player-format") == 0)
optionParseString(key, value, &instance->config.playerFormat);
optionParseString(key, value, &instance->config.player.outputFormat);
else if(strcasecmp(key, "--player-error") == 0)
optionParseString(key, value, &instance->config.player.errorFormat);
else if(strcasecmp(key, "--song-key") == 0)
optionParseString(key, value, &instance->config.songKey);
optionParseString(key, value, &instance->config.song.key);
else if(strcasecmp(key, "--song-format") == 0)
optionParseString(key, value, &instance->config.songFormat);
optionParseString(key, value, &instance->config.song.outputFormat);
else if(strcasecmp(key, "--song-error") == 0)
optionParseString(key, value, &instance->config.song.errorFormat);
else if(strcasecmp(key, "--datetime-key") == 0)
optionParseString(key, value, &instance->config.dateTimeKey);
optionParseString(key, value, &instance->config.dateTime.key);
else if(strcasecmp(key, "--datetime-format") == 0)
optionParseString(key, value, &instance->config.dateTimeFormat);
optionParseString(key, value, &instance->config.dateTime.outputFormat);
else if(strcasecmp(key, "--datetime-error") == 0)
optionParseString(key, value, &instance->config.dateTime.errorFormat);
else if(strcasecmp(key, "--date-key") == 0)
optionParseString(key, value, &instance->config.dateKey);
optionParseString(key, value, &instance->config.date.key);
else if(strcasecmp(key, "--date-format") == 0)
optionParseString(key, value, &instance->config.dateFormat);
optionParseString(key, value, &instance->config.date.outputFormat);
else if(strcasecmp(key, "--date-error") == 0)
optionParseString(key, value, &instance->config.date.errorFormat);
else if(strcasecmp(key, "--time-key") == 0)
optionParseString(key, value, &instance->config.timeKey);
optionParseString(key, value, &instance->config.time.key);
else if(strcasecmp(key, "--time-format") == 0)
optionParseString(key, value, &instance->config.timeFormat);
optionParseString(key, value, &instance->config.time.outputFormat);
else if(strcasecmp(key, "--time-error") == 0)
optionParseString(key, value, &instance->config.time.errorFormat);
else if(strcasecmp(key, "--vulkan-key") == 0)
optionParseString(key, value, &instance->config.vulkan.key);
else if(strcasecmp(key, "--vulkan-format") == 0)
optionParseString(key, value, &instance->config.vulkan.outputFormat);
else if(strcasecmp(key, "--vulkan-error") == 0)
optionParseString(key, value, &instance->config.vulkan.errorFormat);
else if(strcasecmp(key, "--opengl-key") == 0)
optionParseString(key, value, &instance->config.openGL.key);
else if(strcasecmp(key, "--opengl-format") == 0)
optionParseString(key, value, &instance->config.openGL.outputFormat);
else if(strcasecmp(key, "--opengl-error") == 0)
optionParseString(key, value, &instance->config.openGL.errorFormat);
else if(strcasecmp(key, "--opencl-key") == 0)
optionParseString(key, value, &instance->config.openCL.key);
else if(strcasecmp(key, "--opencl-format") == 0)
optionParseString(key, value, &instance->config.openCL.outputFormat);
else if(strcasecmp(key, "--opencl-error") == 0)
optionParseString(key, value, &instance->config.openCL.errorFormat);
///////////////////
//Library options//
@@ -982,12 +1123,24 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.libDBus);
else if(strcasecmp(key, "--lib-XFConf") == 0)
optionParseString(key, value, &instance->config.libXFConf);
else if(strcasecmp(key, "--lib-sqlite") == 0 || strcasecmp(key, "--lib-sqlite3") == 0)
optionParseString(key, value, &instance->config.libSQLite3);
else if(strcasecmp(key, "--lib-rpm") == 0)
optionParseString(key, value, &instance->config.librpm);
else if(strcasecmp(key, "--lib-imagemagick") == 0)
optionParseString(key, value, &instance->config.libImageMagick);
else if(strcasecmp(key, "--lib-z") == 0)
optionParseString(key, value, &instance->config.libZ);
else if(strcasecmp(key, "--lib-chafa") == 0)
optionParseString(key, value, &instance->config.libChafa);
else if(strcasecmp(key, "--lib-egl") == 0)
optionParseString(key, value, &instance->config.libEGL);
else if(strcasecmp(key, "--lib-glx") == 0)
optionParseString(key, value, &instance->config.libGLX);
else if(strcasecmp(key, "--lib-osmesa") == 0)
optionParseString(key, value, &instance->config.libOSMesa);
else if(strcasecmp(key, "--lib-opencl") == 0)
optionParseString(key, value, &instance->config.libOpenCL);
//////////////////
//Module options//
@@ -1011,6 +1164,28 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.playerName);
else if(strcasecmp(key, "--public-ip-timeout") == 0)
instance->config.publicIpTimeout = optionParseUInt32(key, value);
else if(strcasecmp(key, "--gl") == 0)
{
if(value == NULL)
{
fprintf(stderr, "Error: usage: %s <type>\n", key);
exit(491);
}
if(strcasecmp(value, "auto") == 0)
instance->config.glType = FF_GL_TYPE_AUTO;
else if(strcasecmp(value, "egl") == 0)
instance->config.glType = FF_GL_TYPE_EGL;
else if(strcasecmp(value, "glx") == 0)
instance->config.glType = FF_GL_TYPE_GLX;
else if(strcasecmp(value, "osmesa") == 0)
instance->config.glType = FF_GL_TYPE_OSMESA;
else
{
fprintf(stderr, "Error: unknown gl type: %s\n", value);
exit(492);
}
}
//////////////////
//Unknown option//
@@ -1152,6 +1327,12 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
ffPrintTime(instance);
else if(strcasecmp(line, "colors") == 0)
ffPrintColors(instance);
else if(strcasecmp(line, "vulkan") == 0)
ffPrintVulkan(instance);
else if(strcasecmp(line, "opengl") == 0)
ffPrintOpenGL(instance);
else if(strcasecmp(line, "opencl") == 0)
ffPrintOpenCL(instance);
else
ffPrintError(instance, line, 0, NULL, NULL, 0, "<no implementation provided>");
}
+118 -89
View File
@@ -3,20 +3,15 @@
#ifndef FASTFETCH_INCLUDED
#define FASTFETCH_INCLUDED
#include <stddef.h>
#include "fastfetch_config.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/sysinfo.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include "fastfetch_config.h"
#include "util/FFstrbuf.h"
#include "util/FFlist.h"
@@ -38,20 +33,37 @@ typedef enum FFLogoType
FF_LOGO_TYPE_FILE, //Raw text file, printed as is.
FF_LOGO_TYPE_RAW, //Raw text file, printed with color codes replacement.
FF_LOGO_TYPE_SIXEL, //Image file, printed as sixel codes.
FF_LOGO_TYPE_KITTY //Image file, printed as kitty graphics protocol
FF_LOGO_TYPE_KITTY, //Image file, printed as kitty graphics protocol
FF_LOGO_TYPE_CHAFA //Image file, printed as ascii art using libchafa
} FFLogoType;
typedef enum FFGLType
{
FF_GL_TYPE_AUTO,
FF_GL_TYPE_EGL,
FF_GL_TYPE_GLX,
FF_GL_TYPE_OSMESA
} FFGLType;
typedef struct FFModuleArgs
{
FFstrbuf key;
FFstrbuf outputFormat;
FFstrbuf errorFormat;
} FFModuleArgs;
typedef struct FFconfig
{
FFstrbuf logoSource;
FFLogoType logoType;
FFstrbuf logoColors[FASTFETCH_LOGO_MAX_COLORS];
uint32_t logoWidth;
uint32_t logoHeight;
uint32_t logoPaddingLeft;
uint32_t logoPaddingRight;
bool logoPrintRemaining;
FFstrbuf mainColor; //If this is empty, ffPrintLogo will set it to the main color of the logo
FFstrbuf mainColor; //If this is empty, ffLogoPrint will set it to the main color of the logo
FFstrbuf separator;
bool showErrors;
@@ -60,69 +72,44 @@ typedef struct FFconfig
bool allowSlowOperations;
bool disableLinewrap;
bool hideCursor;
bool escapeBedrock;
FFGLType glType;
bool pipe; //disables logo and all escape sequences
FFstrbuf osFormat;
FFstrbuf osKey;
FFstrbuf hostFormat;
FFstrbuf hostKey;
FFstrbuf kernelFormat;
FFstrbuf kernelKey;
FFstrbuf uptimeFormat;
FFstrbuf uptimeKey;
FFstrbuf processesFormat;
FFstrbuf processesKey;
FFstrbuf packagesFormat;
FFstrbuf packagesKey;
FFstrbuf shellFormat;
FFstrbuf shellKey;
FFstrbuf resolutionFormat;
FFstrbuf resolutionKey;
FFstrbuf deFormat;
FFstrbuf deKey;
FFstrbuf wmFormat;
FFstrbuf wmKey;
FFstrbuf wmThemeFormat;
FFstrbuf wmThemeKey;
FFstrbuf themeFormat;
FFstrbuf themeKey;
FFstrbuf iconsFormat;
FFstrbuf iconsKey;
FFstrbuf fontFormat;
FFstrbuf fontKey;
FFstrbuf cursorFormat;
FFstrbuf cursorKey;
FFstrbuf terminalFormat;
FFstrbuf terminalKey;
FFstrbuf termFontFormat;
FFstrbuf termFontKey;
FFstrbuf cpuFormat;
FFstrbuf cpuKey;
FFstrbuf cpuUsageFormat;
FFstrbuf cpuUsageKey;
FFstrbuf gpuFormat;
FFstrbuf gpuKey;
FFstrbuf memoryFormat;
FFstrbuf memoryKey;
FFstrbuf diskFormat;
FFstrbuf diskKey;
FFstrbuf batteryFormat;
FFstrbuf batteryKey;
FFstrbuf localeFormat;
FFstrbuf localeKey;
FFstrbuf localIpKey;
FFstrbuf localIpFormat;
FFstrbuf publicIpKey;
FFstrbuf publicIpFormat;
FFstrbuf playerKey;
FFstrbuf playerFormat;
FFstrbuf songKey;
FFstrbuf songFormat;
FFstrbuf dateTimeKey;
FFstrbuf dateTimeFormat;
FFstrbuf dateKey;
FFstrbuf dateFormat;
FFstrbuf timeKey;
FFstrbuf timeFormat;
FFModuleArgs os;
FFModuleArgs host;
FFModuleArgs kernel;
FFModuleArgs uptime;
FFModuleArgs processes;
FFModuleArgs packages;
FFModuleArgs shell;
FFModuleArgs resolution;
FFModuleArgs de;
FFModuleArgs wm;
FFModuleArgs wmTheme;
FFModuleArgs theme;
FFModuleArgs icons;
FFModuleArgs font;
FFModuleArgs cursor;
FFModuleArgs terminal;
FFModuleArgs terminalFont;
FFModuleArgs cpu;
FFModuleArgs cpuUsage;
FFModuleArgs gpu;
FFModuleArgs memory;
FFModuleArgs disk;
FFModuleArgs battery;
FFModuleArgs locale;
FFModuleArgs localIP;
FFModuleArgs publicIP;
FFModuleArgs player;
FFModuleArgs song;
FFModuleArgs dateTime;
FFModuleArgs date;
FFModuleArgs time;
FFModuleArgs vulkan;
FFModuleArgs openGL;
FFModuleArgs openCL;
FFstrbuf libPCI;
FFstrbuf libVulkan;
@@ -135,9 +122,15 @@ typedef struct FFconfig
FFstrbuf libDConf;
FFstrbuf libDBus;
FFstrbuf libXFConf;
FFstrbuf libSQLite3;
FFstrbuf librpm;
FFstrbuf libImageMagick;
FFstrbuf libZ;
FFstrbuf libChafa;
FFstrbuf libEGL;
FFstrbuf libGLX;
FFstrbuf libOSMesa;
FFstrbuf libOpenCL;
FFstrbuf diskFolders;
@@ -176,6 +169,14 @@ typedef struct FFinstance
FFstate state;
} FFinstance;
typedef struct FFVersion
{
uint32_t major;
uint32_t minor;
uint32_t patch;
} FFVersion;
#define FF_VERSION_INIT ((FFVersion) {0})
typedef struct FFTitleResult
{
FFstrbuf userName;
@@ -231,6 +232,22 @@ typedef struct FFTerminalShellResult
FFstrbuf userShellVersion;
} FFTerminalShellResult;
typedef struct FFGPUResult
{
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
double temperature;
} FFGPUResult;
typedef struct FFVulkanResult
{
FFstrbuf driver;
FFstrbuf apiVersion;
FFstrbuf conformanceVersion;
FFlist devices; //List of FFGPUResult
} FFVulkanResult;
typedef struct FFResolutionResult
{
uint32_t width;
@@ -252,8 +269,8 @@ typedef struct FFDisplayServerResult
typedef struct FFTempValue
{
FFstrbuf name;
FFstrbuf value;
FFstrbuf deviceClass;
double value;
} FFTempValue;
typedef struct FFTempsResult
@@ -405,11 +422,14 @@ bool ffWriteFileContent(const char* fileName, const FFstrbuf* buffer);
bool ffFileExists(const char* fileName, mode_t mode);
void ffSuppressIO(bool suppress); // Not thread safe!
void ffGetTerminalResponse(const char* request, char end, const char* format, ...);
void ffGetTerminalResponse(const char* request, const char* format, ...);
//common/printing.c
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...);
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);
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);
@@ -419,9 +439,9 @@ 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 FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t 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);
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* value, const FFstrbuf* formatString, uint32_t numArgs, const FFformatarg* arguments);
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);
//common/properties.c
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer);
@@ -441,13 +461,16 @@ void ffFontDestroy(FFfont* font);
//common/format.c
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
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);
//common/parsing.c
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);
//common/processing.c
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
@@ -463,6 +486,8 @@ FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, c
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__
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
#endif
@@ -471,15 +496,13 @@ bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
// Logo functions //
////////////////////
void ffPrintLogo(FFinstance* instance);
void ffPrintRemainingLogo(FFinstance* instance);
void ffLogoPrint(FFinstance* instance);
void ffLogoPrintRemaining(FFinstance* instance);
void ffLogoPrintLine(FFinstance* instance);
void ffPrintLogoLine(FFinstance* instance);
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat);
void ffPrintBuiltinLogos(FFinstance* instance);
void ffListBuiltinLogos();
void ffListBuiltinLogosAutocompletion();
void ffLogoBuiltinPrint(FFinstance* instance);
void ffLogoBuiltinList();
void ffLogoBuiltinListAutocompletion();
/////////////////////////
// Detection functions //
@@ -511,6 +534,9 @@ const FFMediaResult* ffDetectMedia(FFinstance* instance);
//detection/dateTime.c
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance);
//detection/vulkan.c
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance);
//////////////////////
// Module functions //
//////////////////////
@@ -518,7 +544,7 @@ const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance);
//Common
const FFTitleResult* ffDetectTitle(FFinstance* instance);
void ffPrintDateTimeFormat(FFinstance* instance, const char* moduleName, const FFstrbuf* key, const FFstrbuf* format);
void ffPrintDateTimeFormat(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs);
//Printing
@@ -558,5 +584,8 @@ void ffPrintTime(FFinstance* instance);
void ffPrintLocalIp(FFinstance* instance);
void ffPrintPublicIp(FFinstance* instance);
void ffPrintColors(FFinstance* instance);
void ffPrintVulkan(FFinstance* instance);
void ffPrintOpenGL(FFinstance* instance);
void ffPrintOpenCL(FFinstance* instance);
#endif
+2
View File
@@ -4,6 +4,8 @@
#define FASTFETCH_PROJECT_NAME "@PROJECT_NAME@"
#define FASTFETCH_PROJECT_VERSION "@PROJECT_VERSION@"
#define FASTFETCH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define FASTFETCH_PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define FASTFETCH_PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define FASTFETCH_PROJECT_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@"
#define FASTFETCH_TARGET_DIR_ROOT "@TARGET_DIR_ROOT@"
+2
View File
@@ -50,6 +50,8 @@ int main(int argc, char** argv)
//ffPrintDateTime(&instance);
//ffPrintDate(&instance);
//ffPrintTime(&instance);
//ffPrintVulkan(&instance);
//ffPrintOpenGL(&instance);
ffPrintBreak(&instance);
ffPrintColors(&instance);
+263 -203
View File
@@ -1,28 +1,15 @@
#include "logo.h"
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
typedef struct FFlogo
{
const char* data;
const char** names; //Null terminated
const char** builtinColors; //Null terminated
bool performColorReplacement;
} FFlogo;
#define FF_LOGO_INIT static FFlogo logo; static bool init = false; if(init) return &logo; init = true;
#define FF_LOGO_NAMES(...) static const char* names[] = (const char*[]) { __VA_ARGS__, NULL }; logo.names = names;
#define FF_LOGO_LINES(x) logo.data = x;
#define FF_LOGO_COLORS(...) static const char* colors[] = (const char*[]) { __VA_ARGS__, NULL }; logo.builtinColors = colors;
#define FF_LOGO_RETURN return &logo;
static const FFlogo* getLogoUnknown()
const FFlogo* ffLogoBuiltinGetUnknown()
{
FF_LOGO_INIT
FF_LOGO_NAMES("unkown", "question mark", "?")
FF_LOGO_NAMES("unknown", "question mark", "?")
FF_LOGO_LINES(
" ________\n"
" _jgN########Ngg_\n"
@@ -56,6 +43,56 @@ static const FFlogo* getLogoNone()
FF_LOGO_RETURN
}
static const FFlogo* getLogoAlpine()
{
FF_LOGO_INIT
FF_LOGO_NAMES("alpine", "alpinelinux", "alpine-linux")
FF_LOGO_LINES(
" .hddddddddddddddddddddddh.\n"
" :dddddddddddddddddddddddddd:\n"
" /dddddddddddddddddddddddddddd/\n"
" +dddddddddddddddddddddddddddddd+\n"
" `sdddddddddddddddddddddddddddddddds`\n"
" `ydddddddddddd++hdddddddddddddddddddy`\n"
".hddddddddddd+` `+ddddh:-sdddddddddddh. \n"
"hdddddddddd+` `+y: .sddddddddddh\n"
"ddddddddh+` `//` `.` -sddddddddd\n"
"ddddddh+` `/hddh/` `:s- -sddddddd\n"
"ddddh+` `/+/dddddh/` `+s- -sddddd\n"
"ddd+` `/o` :dddddddh/` `oy- .yddd\n"
"hdddyo+ohddyosdddddddddho+oydddy++ohdddh\n"
".hddddddddddddddddddddddddddddddddddddh.\n"
" `yddddddddddddddddddddddddddddddddddy`\n"
" `sdddddddddddddddddddddddddddddddds`\n"
" +dddddddddddddddddddddddddddddd+\n"
" /dddddddddddddddddddddddddddd/\n"
" :dddddddddddddddddddddddddd:\n"
" .hddddddddddddddddddddddh.";
)
FF_LOGO_COLORS(
"34" //blue
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoAlpineSmall()
{
FF_LOGO_INIT
FF_LOGO_NAMES("alpine_small", "alpine-linux-small")
FF_LOGO_LINES(
" /\\ /\\\n"
" // \\ \\\n"
" // \\ \\\n"
"/// \\ \\\n"
"// \\ \\\n"
" \\"
)
FF_LOGO_COLORS(
"34" //blue
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoAndroid()
{
FF_LOGO_INIT
@@ -239,6 +276,36 @@ static const FFlogo* getLogoArcoLinux()
FF_LOGO_RETURN
}
static const FFlogo* getLogoBedrock()
{
FF_LOGO_INIT
FF_LOGO_NAMES("bedrock", "bedrocklinux", "bedrock-linux")
FF_LOGO_LINES(
"--------------------------------------\n"
"--------------------------------------\n"
"--------------------------------------\n"
"---$2\\\\\\\\\\\\\\\\\\\\\\\\$1-----------------------\n"
"----$2\\\\\\ \\\\\\$1----------------------\n"
"-----$2\\\\\\ \\\\\\$1---------------------\n"
"------$2\\\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\$1------\n"
"-------$2\\\\\\ \\\\\\$1-----\n"
"--------$2\\\\\\ \\\\\\$1----\n"
"---------$2\\\\\\ ______ \\\\\\$1---\n"
"----------$2\\\\\\ ///$1---\n"
"-----------$2\\\\\\ ///$1----\n"
"------------$2\\\\\\ ///$1-----\n"
"-------------$2\\\\\\////////////////$1------\n"
"--------------------------------------\n"
"--------------------------------------\n"
"--------------------------------------"
)
FF_LOGO_COLORS(
"90", //grey
"37" //white
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoCachyOS()
{
FF_LOGO_INIT
@@ -408,6 +475,82 @@ static const FFlogo* getLogoDebianSmall()
FF_LOGO_RETURN
}
static const FFlogo* getLogoDevuan()
{
FF_LOGO_INIT
FF_LOGO_NAMES("devuan", "devuan-linux")
FF_LOGO_LINES(
" ..,,;;;::;,..\n"
" `':ddd;:,.\n"
" `'dPPd:,.\n"
" `:b$$b`.\n"
" 'P$$$d`\n"
" .$$$$$`\n"
" ;$$$$$P\n"
" .:P$$$$$$`\n"
" .,:b$$$$$$$;'\n"
" .,:dP$$$$$$$$b:'\n"
" .,:;db$$$$$$$$$$Pd'`\n"
" ,db$$$$$$$$$$$$$$b:'`\n"
":$$$$$$$$$$$$b:'`\n"
" `$$$$$bd:''`\n"
" `'''`\n"
)
FF_LOGO_COLORS(
"35" //magenta
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoDevuanSmall()
{
FF_LOGO_INIT
FF_LOGO_NAMES("devuan_small", "devuan-linux-small")
FF_LOGO_LINES(
" ..:::.\n"
" ..-==-\n"
" .+#:\n"
" =@@\n"
" :+%@#:\n"
".:=+#@@%*:\n"
"#@@@#=:\n"
)
FF_LOGO_COLORS(
"34" //blue
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoDeepin()
{
FF_LOGO_INIT
FF_LOGO_NAMES("deepin", "deepin-linux")
FF_LOGO_LINES(
"$1 ............\n"
" .';;;;;. .,;,.\n"
" .,;;;;;;;. ';;;;;;;.\n"
" .;::::::::' .,::;;,''''',.\n"
" ,'.:::::::: .;;'. ';\n"
" ;' 'cccccc, ,' :: '.. .:\n"
" ,, :ccccc. ;: .c, '' :. ,;\n"
".l. cllll' ., .lc :; .l' l.\n"
".c :lllc ;cl: .l' .ll. :'\n"
".l 'looc. . ,o: 'oo' c,\n"
".o. .:ool::coc' .ooo' o.\n"
" :: ..... .;dddo ;c\n"
" l:... .';lddddo. ,o\n"
" lxxxxxdoolllodxxxxxxxxxc :l\n"
" ,dxxxxxxxxxxxxxxxxxxl. 'o,\n"
" ,dkkkkkkkkkkkkko;. .;o;\n"
" .;okkkkkdl;. .,cl:.\n"
" .,:cccccccc:,."
)
FF_LOGO_COLORS(
"32" //green
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoEndeavour()
{
FF_LOGO_INIT
@@ -632,6 +775,39 @@ static const FFlogo* getLogoKDENeon()
FF_LOGO_RETURN
}
static const FFlogo* getLogoKubuntu()
{
FF_LOGO_INIT
FF_LOGO_NAMES("kubuntu", "kubuntu-linux", "kde-ubuntu", "ubuntu-kde", "ubuntu-plasma")
FF_LOGO_LINES(
"$1 `.:/ossyyyysso/:.\n"
" .:oyyyyyyyyyyyyyyyyyyo:`\n"
" -oyyyyyyyo$2dMMy$1yyyyyyysyyyyo-\n"
" -syyyyyyyyyy$2dMMy$1oyyyy$2dmMMy$1yyyys-\n"
" oyyys$2dMy$1syyyy$2dMMMMMMMMMMMMMy$1yyyyyyo\n"
" `oyyyy$2dMMMMy$1syysoooooo$2dMMMMy$1yyyyyyyyo`\n"
" oyyyyyy$2dMMMMy$1yyyyyyyyyyys$2dMMy$1sssssyyyo\n"
"-yyyyyyyy$2dMy$1syyyyyyyyyyyyyys$2dMMMMMy$1syyy-\n"
"oyyyysoo$2dMy$1yyyyyyyyyyyyyyyyyy$2dMMMMy$1syyyo\n"
"yyys$2dMMMMMy$1yyyyyyyyyyyyyyyyyysosyyyyyyyy\n"
"yyys$2dMMMMMy$1yyyyyyyyyyyyyyyyyyyyyyyyyyyyy\n"
"oyyyyysos$2dy$1yyyyyyyyyyyyyyyyyy$2dMMMMy$1syyyo\n"
"-yyyyyyyy$2dMy$1syyyyyyyyyyyyyys$2dMMMMMy$1syyy-\n"
" oyyyyyy$2dMMMy$1syyyyyyyyyyys$2dMMy$1oyyyoyyyo\n"
" `oyyyy$2dMMMy$1syyyoooooo$2dMMMMy$1oyyyyyyyyo\n"
" oyyysyyoyyyys$2dMMMMMMMMMMMy$1yyyyyyyo\n"
" -syyyyyyyyy$2dMMMy$1syyy$2dMMMy$1syyyys-\n"
" -oyyyyyyy$2dMMy$1yyyyyysosyyyyo-\n"
" ./oyyyyyyyyyyyyyyyyyyo/.\n"
" `.:/oosyyyysso/:.`"
)
FF_LOGO_COLORS(
"34", //blue
"37" //white
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoLinux()
{
FF_LOGO_INIT
@@ -1112,6 +1288,67 @@ static const FFlogo* getLogoRedHatEnterpriseLinux()
FF_LOGO_RETURN
}
static const FFlogo* getLogoRedstarOS()
{
FF_LOGO_INIT
FF_LOGO_NAMES("redstar", "redstar-os", "redstaros", "redstaros-linux", "redstar-os-linux")
FF_LOGO_LINES(
"$1 ..\n"
" .oK0l\n"
" :0KKKKd.\n"
" .xKO0KKKKd\n"
" ,Od' .d0000l\n"
" .c;. .'''... ..'.\n"
".,:cloddxxxkkkkOOOOkkkkkkkkxxxxxxxxxkkkx:\n"
";kOOOOOOOkxOkc'...',;;;;,,,'',;;:cllc:,.\n"
" .okkkkd,.lko .......',;:cllc:;,,'''''.\n"
" .cdo. :xd' cd:. ..';'',,,'',,;;;,'.\n"
" . .ddl.;doooc'..;oc;'..';::;,'.\n"
" coo;.oooolllllllcccc:'. .\n"
" .ool''lllllccccccc:::::;.\n"
" ;lll. .':cccc:::::::;;;;'\n"
" :lcc:'',..';::::;;;;;;;,,.\n"
" :cccc::::;...';;;;;,,,,,,.\n"
" ,::::::;;;,'. ..',,,,'''.\n"
" ........ ......"
)
FF_LOGO_COLORS(
"31" //red
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoRockyLinux()
{
FF_LOGO_INIT
FF_LOGO_NAMES("rocky", "rocky-linux", "rockylinux")
FF_LOGO_LINES(
" __wgliliiligw_,\n"
" _williiiiiiliilililw,\n"
" _%iiiiiilililiiiiiiiiiii_\n"
" .Qliiiililiiiiiiililililiilm.\n"
" _iiiiiliiiiiililiiiiiiiiiiliil,\n"
" .lililiiilililiiiilililililiiiii,\n"
"_liiiiiiliiiiiiiliiiiiF{iiiiiilili,\n"
"jliililiiilililiiili@` ~ililiiiiiL\n"
"iiiliiiiliiiiiiili>` ~liililii\n"
"liliiiliiilililii` -9liiiil\n"
"iiiiiliiliiiiii~ ''4lili\n"
"4ililiiiiilil~| -w, )4lf\n"
"-liiiiililiF' _liig, )'\n"
" )iiiliii@` _QIililig,\n"
" )iiii>` .Qliliiiililw\n"
" )<>~ .mliiiiiliiiiiil,\n"
" _gllilililiililii~\n"
" giliiiiiiiiiiiiT`\n"
" -^~$ililili@~~'"
)
FF_LOGO_COLORS(
"32" //green
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoUbuntu()
{
FF_LOGO_INIT
@@ -1242,13 +1479,13 @@ static const FFlogo* getLogoZorin()
FF_LOGO_RETURN
}
typedef const FFlogo*(*GetLogoMethod)();
static GetLogoMethod* getLogos()
GetLogoMethod* ffLogoBuiltinGetAll()
{
static GetLogoMethod logoMethods[] = {
ffLogoBuiltinGetUnknown,
getLogoNone,
getLogoUnknown,
getLogoAlpine,
getLogoAlpineSmall,
getLogoAndroid,
getLogoAndroidSmall,
getLogoArch,
@@ -1256,12 +1493,16 @@ static GetLogoMethod* getLogos()
getLogoArcoLinux,
getLogoArtix,
getLogoArtixSmall,
getLogoBedrock,
getLogoCachyOS,
getLogoCelOS,
getLogoCentOS,
getLogoCentOSSmall,
getLogoDebian,
getLogoDevuan,
getLogoDevuanSmall,
getLogoDebianSmall,
getLogoDeepin,
getLogoEndeavour,
getLogoFedora,
getLogoFedoraSmall,
@@ -1270,6 +1511,7 @@ static GetLogoMethod* getLogos()
getLogoGentoo,
getLogoGentooSmall,
getLogoKDENeon,
getLogoKubuntu,
getLogoLinux,
getLogoManjaro,
getLogoManjaroSmall,
@@ -1288,6 +1530,8 @@ static GetLogoMethod* getLogos()
getLogoReborn,
getLogoRebornSmall,
getLogoRedHatEnterpriseLinux,
getLogoRedstarOS,
getLogoRockyLinux,
getLogoUbuntu,
getLogoUbuntuSmall,
getLogoVoid,
@@ -1298,187 +1542,3 @@ static GetLogoMethod* getLogos()
return logoMethods;
}
static bool logoHasName(const FFlogo* logo, const char* name)
{
const char** logoName = logo->names;
while(*logoName != NULL)
{
if(strcasecmp(*logoName, name) == 0)
return true;
++logoName;
}
return false;
}
static const FFlogo* getBuiltinLogo(const char* name)
{
GetLogoMethod* methods = getLogos();
while(*methods != NULL)
{
const FFlogo* logo = (*methods)();
if(logoHasName(logo, name))
return logo;
++methods;
}
return NULL;
}
static const FFlogo* detectBuiltinLogoWithVersion(const FFstrbuf* versionString, const FFstrbuf* name)
{
if(versionString->length == 0)
return getBuiltinLogo(name->chars);
#define FF_PRINT_LOGO_VERSIONED_IF_EXISTS(newLogo, oldLogo, ver) \
if(logoHasName(newLogo, name->chars)) \
{ \
long version = strtol(versionString->chars, NULL, 10); \
return (version == 0 || version == LONG_MAX || version == LONG_MIN || version > ver) ? newLogo : oldLogo; \
}
FF_PRINT_LOGO_VERSIONED_IF_EXISTS(getLogoFedora(), getLogoFedoraOld(), 34)
FF_PRINT_LOGO_VERSIONED_IF_EXISTS(getLogoMint(), getLogoMintOld(), 19)
return getBuiltinLogo(name->chars);
}
static const FFlogo* detectBuiltinLogo(const FFinstance* instance)
{
static const FFlogo* logo;
static bool detected = false;
if(detected)
return logo;
detected = true;
const FFOSResult* os = ffDetectOS(instance);
logo = detectBuiltinLogoWithVersion(&os->version, &os->name);
if(logo != NULL)
return logo;
logo = detectBuiltinLogoWithVersion(&os->version, &os->id);
if(logo != NULL)
return logo;
logo = detectBuiltinLogoWithVersion(&os->version, &os->idLike);
if(logo != NULL)
return logo;
logo = detectBuiltinLogoWithVersion(&os->version, &os->systemName);
if(logo != NULL)
return logo;
return getLogoUnknown();
}
void ffLogoSetMainColor(FFinstance* instance)
{
const FFlogo* logo = NULL;
if(instance->config.logoSource.length > 0)
logo = getBuiltinLogo(instance->config.logoSource.chars);
if(logo == NULL)
logo = detectBuiltinLogo(instance);
ffStrbufAppendS(&instance->config.mainColor, logo->builtinColors[0]);
}
static void printLogoStruct(FFinstance* instance, const FFlogo* logo, bool doColorReplacement)
{
if(!doColorReplacement)
{
ffLogoPrint(instance, logo->data, false);
return;
}
const char** colors = logo->builtinColors;
for(int i = 0; *colors != NULL && i < FASTFETCH_LOGO_MAX_COLORS; i++, colors++)
{
if(instance->config.logoColors[i].length == 0)
ffStrbufAppendS(&instance->config.logoColors[i], *colors);
}
ffLogoPrint(instance, logo->data, true);
}
void ffLogoPrintUnknown(FFinstance* instance)
{
printLogoStruct(instance, getLogoUnknown(), false);
}
bool ffLogoPrintBuiltinIfExists(FFinstance* instance)
{
const FFlogo* logo = getBuiltinLogo(instance->config.logoSource.chars);
if(logo == NULL)
return false;
printLogoStruct(instance, logo, true);
return true;
}
void ffLogoPrintBuiltinDetected(FFinstance* instance)
{
printLogoStruct(instance, detectBuiltinLogo(instance), true);
}
void ffPrintBuiltinLogos(FFinstance* instance)
{
GetLogoMethod* methods = getLogos();
while(*methods != NULL)
{
const FFlogo* logo = (*methods)();
printf("\033[%sm%s:\033[0m\n", logo->builtinColors[0], logo->names[0]);
printLogoStruct(instance, logo, true);
ffPrintRemainingLogo(instance);
instance->state.logoHeight = 0;
for(uint8_t i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
ffStrbufClear(&instance->config.logoColors[i]);
puts("\n");
++methods;
}
}
void ffListBuiltinLogos()
{
GetLogoMethod* methods = getLogos();
uint32_t counter = 0;
while(*methods != NULL)
{
const FFlogo* logo = (*methods)();
const char** names = logo->names;
printf("%u)%s ", counter, counter < 10 ? " " : "");
++counter;
while(*names != NULL)
{
printf("\"%s\" ", *names);
++names;
}
putchar('\n');
++methods;
}
}
void ffListBuiltinLogosAutocompletion()
{
GetLogoMethod* methods = getLogos();
while(*methods != NULL)
{
printf("%s\n", (*methods)()->names[0]);
++methods;
}
}
+2
View File
@@ -1,6 +1,8 @@
#ifdef FF_HAVE_IMAGEMAGICK6
#include "image.h"
#include <dlfcn.h>
#include <magick/MagickCore.h>
static FF_LIBRARY_SYMBOL(ResizeImage);
+2
View File
@@ -1,6 +1,8 @@
#ifdef FF_HAVE_IMAGEMAGICK7
#include "image.h"
#include <dlfcn.h>
#include <MagickCore/MagickCore.h>
static FF_LIBRARY_SYMBOL(ResizeImage);
+254 -85
View File
@@ -5,15 +5,20 @@
#define FF_KITTY_MAX_CHUNK_SIZE 4096
#define FF_CACHE_FILE_HEIGHT "height"
#define FF_CACHE_FILE_WIDTH "width"
#define FF_CACHE_FILE_SIXEL "sixel"
#define FF_CACHE_FILE_KITTY_COMPRESSED "kittyc"
#define FF_CACHE_FILE_KITTY_UNCOMPRESSED "kittyu"
#define FF_CACHE_FILE_CHAFA "chafa"
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef FF_HAVE_ZLIB
#include <stdlib.h>
#include <dlfcn.h>
#include <zlib.h>
static bool compressBlob(const FFinstance* instance, void** blob, size_t* length)
@@ -79,42 +84,54 @@ static inline bool checkAllocationResult(void* data, size_t length)
return true;
}
static void finishPrinting(FFinstance* instance, const FFLogoRequestData* requestData)
static inline uint32_t simpleCeil(double value)
{
instance->state.logoWidth = (uint32_t) (requestData->imagePixelWidth / requestData->characterPixelWidth) + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
instance->state.logoHeight = (uint32_t) (requestData->imagePixelHeight / requestData->characterPixelHeight);
//Seems to be required on all consoles that support sixel. TBH i don't know why.
if(requestData->type == FF_LOGO_TYPE_SIXEL)
instance->state.logoHeight += 1;
fputs("\033[9999999D", stdout);
printf("\033[%uA", instance->state.logoHeight);
uint32_t result = (uint32_t) value;
return value == (double) result ? result : result + 1;
}
static void writeResult(FFinstance* instance, FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName)
static void writeCacheStrbuf(FFLogoRequestData* requestData, const FFstrbuf* value, const char* cacheFileName)
{
uint32_t cacheDirLength = requestData->cacheDir.length;
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
ffWriteFileContent(requestData->cacheDir.chars, value);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
}
static void writeCacheUint32(FFLogoRequestData* requestData, uint32_t value, const char* cacheFileName)
{
FFstrbuf content;
content.chars = (char*) &value;
content.length = sizeof(value);
writeCacheStrbuf(requestData, &content, cacheFileName);
}
static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName)
{
//Calculate character dimensions
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
instance->state.logoHeight = requestData->logoCharacterHeight;
if(requestData->type == FF_LOGO_TYPE_KITTY)
instance->state.logoHeight -= 1;
//Write cache files
writeCacheStrbuf(requestData, result, cacheFileName);
if(instance->config.logoWidth == 0)
writeCacheUint32(requestData, instance->state.logoWidth, FF_CACHE_FILE_WIDTH);
if(instance->config.logoHeight == 0)
writeCacheUint32(requestData, instance->state.logoHeight, FF_CACHE_FILE_HEIGHT);
//Write result to stdout
ffPrintCharTimes(' ', instance->config.logoPaddingLeft);
fflush(stdout);
ffWriteFDContent(STDOUT_FILENO, result);
//Write result to cache file
uint32_t cacheDirLength = requestData->cacheDir.length;
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
ffWriteFileContent(requestData->cacheDir.chars, result);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
//Write height cache file
ffStrbufAppendS(&requestData->cacheDir, FF_CACHE_FILE_HEIGHT);
FFstrbuf content;
content.chars = (char*) &requestData->imagePixelHeight;
content.length = sizeof(requestData->imagePixelHeight);
ffWriteFileContent(requestData->cacheDir.chars, &content);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
//Write escape codes to stdout
finishPrinting(instance, requestData);
//Go to upper left corner
fputs("\033[9999999D", stdout);
printf("\033[%uA", instance->state.logoHeight);
}
static bool printImageSixel(FFinstance* instance, FFLogoRequestData* requestData, const ImageData* imageData)
@@ -130,7 +147,7 @@ static bool printImageSixel(FFinstance* instance, FFLogoRequestData* requestData
result.chars = (char*) blob;
result.length = (uint32_t) length;
writeResult(instance, requestData, &result, FF_CACHE_FILE_SIXEL);
printImagePixels(instance, requestData, &result, FF_CACHE_FILE_SIXEL);
free(blob);
return true;
@@ -179,20 +196,79 @@ static bool printImageKitty(FFinstance* instance, FFLogoRequestData* requestData
const char* currentPos = chars;
size_t remainingLength = length;
ffStrbufAppendF(&result, "\033_Ga=T,f=32,s=%u,v=%u", requestData->imagePixelWidth, requestData->imagePixelHeight);
ffStrbufAppendF(&result, "\033_Ga=T,f=32,s=%u,v=%u", requestData->logoPixelWidth, requestData->logoPixelHeight);
if(isCompressed)
ffStrbufAppendS(&result, ",o=z");
appendKittyChunk(&result, &currentPos, &remainingLength, false);
while(remainingLength > 0)
appendKittyChunk(&result, &currentPos, &remainingLength, true);
writeResult(instance, requestData, &result, isCompressed ? FF_CACHE_FILE_KITTY_COMPRESSED : FF_CACHE_FILE_KITTY_UNCOMPRESSED);
printImagePixels(instance, requestData, &result, isCompressed ? FF_CACHE_FILE_KITTY_COMPRESSED : FF_CACHE_FILE_KITTY_UNCOMPRESSED);
ffStrbufDestroy(&result);
free(chars);
return true;
}
#ifdef FF_HAVE_CHAFA
#include <chafa/chafa.h>
static bool printImageChafa(FFinstance* instance, FFLogoRequestData* requestData, const ImageData* imageData)
{
FF_LIBRARY_LOAD(chafa, instance->config.libChafa, false, "libchafa.so", 1)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_new, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_add_by_tags, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_new, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_set_geometry, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_set_symbol_map, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_new, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_draw_all_pixels, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_print, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_unref, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_unref, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_unref, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, g_string_free, false)
imageData->ffCopyMagickString(imageData->imageInfo->magick, "RGBA", 5);
size_t length;
void* blob = imageData->ffImageToBlob(imageData->imageInfo, imageData->image, &length, imageData->exceptionInfo);
if(!checkAllocationResult(blob, length))
return false;
ChafaSymbolMap* symbolMap = ffchafa_symbol_map_new();
ffchafa_symbol_map_add_by_tags(symbolMap, CHAFA_SYMBOL_TAG_ALL);
ChafaCanvasConfig* canvasConfig = ffchafa_canvas_config_new();
ffchafa_canvas_config_set_geometry(canvasConfig, (gint) requestData->logoCharacterWidth, (gint) requestData->logoCharacterHeight);
ffchafa_canvas_config_set_symbol_map(canvasConfig, symbolMap);
ChafaCanvas* canvas = ffchafa_canvas_new(canvasConfig);
ffchafa_canvas_draw_all_pixels(
canvas,
CHAFA_PIXEL_RGBA8_UNASSOCIATED,
blob,
(gint) imageData->image->columns,
(gint) imageData->image->rows,
(gint) imageData->image->columns * 4
);
GString* str = ffchafa_canvas_print(canvas, NULL);
FFstrbuf result;
result.allocated = (uint32_t) str->allocated_len;
result.length = (uint32_t) str->len;
result.chars = str->str;
ffLogoPrintChars(instance, result.chars, false);
writeCacheStrbuf(requestData, &result, FF_CACHE_FILE_CHAFA);
ffg_string_free(str, TRUE);
ffchafa_canvas_unref(canvas);
ffchafa_canvas_config_unref(canvasConfig);
ffchafa_symbol_map_unref(symbolMap);
return true;
}
#endif
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData* requestData, const FFIMData* imData)
{
FF_LIBRARY_LOAD_SYMBOL(imData->library, AcquireExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
@@ -222,31 +298,43 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData*
//+1, because we need to copy the null byte too
imageData.ffCopyMagickString(imageInfoIn->filename, instance->config.logoSource.chars, instance->config.logoSource.length + 1);
Image* originalImage = ffReadImage(imageInfoIn, imageData.exceptionInfo);
imageData.image = ffReadImage(imageInfoIn, imageData.exceptionInfo);
ffDestroyImageInfo(imageInfoIn);
if(originalImage == NULL)
{
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
//imagePixelWidth is set in ffLogoPrintImageIfExists
requestData->imagePixelHeight = (uint32_t) ((requestData->imagePixelWidth / (double) originalImage->columns) * (double) originalImage->rows);
if(requestData->imagePixelHeight < 1)
{
ffDestroyImage(originalImage);
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
imageData.image = (Image*) imData->resizeFunc(originalImage, requestData->imagePixelWidth, requestData->imagePixelHeight, imageData.exceptionInfo);
ffDestroyImage(originalImage);
if(imageData.image == NULL)
{
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
if(requestData->logoPixelWidth == 0 && requestData->logoPixelHeight == 0)
{
requestData->logoPixelWidth = (uint32_t) imageData.image->columns;
requestData->logoPixelHeight = (uint32_t) imageData.image->rows;
}
else if(requestData->logoPixelWidth == 0)
requestData->logoPixelWidth = (uint32_t) ((double) imageData.image->columns / (double) imageData.image->rows * requestData->logoPixelHeight);
else if(requestData->logoPixelHeight == 0)
requestData->logoPixelHeight = (uint32_t) ((double) imageData.image->rows / (double) imageData.image->columns * requestData->logoPixelWidth);
requestData->logoCharacterWidth = simpleCeil((double) requestData->logoPixelWidth / requestData->characterPixelWidth);
requestData->logoCharacterHeight = simpleCeil((double) requestData->logoPixelHeight / requestData->characterPixelHeight);
if(requestData->logoPixelWidth == 0 || requestData->logoPixelHeight == 0 || requestData->logoCharacterWidth == 0 || requestData->logoCharacterHeight == 0)
{
ffDestroyImage(imageData.image);
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
Image* resized = imData->resizeFunc(imageData.image, requestData->logoPixelWidth, requestData->logoPixelHeight, imageData.exceptionInfo);
ffDestroyImage(imageData.image);
if(resized == NULL)
{
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
imageData.image = resized;
imageData.imageInfo = ffAcquireImageInfo();
if(imageData.imageInfo == NULL)
{
@@ -255,10 +343,16 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData*
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
bool printSuccessful;
if(requestData->type == FF_LOGO_TYPE_KITTY)
bool printSuccessful = false;
if(requestData->type == FF_LOGO_TYPE_CHAFA)
{
#ifdef FF_HAVE_CHAFA
printSuccessful = printImageChafa(instance, requestData, &imageData);
#endif
}
else if(requestData->type == FF_LOGO_TYPE_KITTY)
printSuccessful = printImageKitty(instance, requestData, &imageData);
else
else if(requestData->type == FF_LOGO_TYPE_SIXEL)
printSuccessful = printImageSixel(instance, requestData, &imageData);
ffDestroyImageInfo(imageData.imageInfo);
@@ -277,32 +371,80 @@ static int getCacheFD(FFLogoRequestData* requestData, const char* fileName)
return fd;
}
static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
static void readCachedStrbuf(FFLogoRequestData* requestData, FFstrbuf* result, const char* cacheFileName)
{
uint32_t cacheDirLength = requestData->cacheDir.length;
ffStrbufAppendS(&requestData->cacheDir, FF_CACHE_FILE_HEIGHT);
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
ffAppendFileContent(requestData->cacheDir.chars, result);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
}
static uint32_t readCachedUint32(FFLogoRequestData* requestData, const char* cacheFileName)
{
FFstrbuf content;
ffStrbufInitA(&content, sizeof(requestData->imagePixelHeight) + 1); // +1 because strbuf is null terminated
memset(content.chars, 0, sizeof(requestData->imagePixelHeight));
ffStrbufInit(&content);
readCachedStrbuf(requestData, &content, cacheFileName);
ffAppendFileContent(requestData->cacheDir.chars, &content);
memcpy(&requestData->imagePixelHeight, content.chars, sizeof(requestData->imagePixelHeight));
uint32_t result = 0;
if(content.length != sizeof(result))
{
ffStrbufDestroy(&content);
return 0;
}
memcpy(&result, content.chars, sizeof(result));
ffStrbufDestroy(&content);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
if(requestData->imagePixelHeight < 1)
return result;
}
static bool printCachedChars(FFinstance* instance, FFLogoRequestData* requestData)
{
FFstrbuf content;
ffStrbufInitA(&content, 32768);
if(requestData->type == FF_LOGO_TYPE_CHAFA)
readCachedStrbuf(requestData, &content, FF_CACHE_FILE_CHAFA);
if(content.length == 0)
{
ffStrbufDestroy(&content);
return false;
}
int fd;
ffLogoPrintChars(instance, content.chars, false);
ffStrbufDestroy(&content);
return true;
}
static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestData)
{
requestData->logoCharacterWidth = instance->config.logoWidth;
if(requestData->logoCharacterWidth == 0)
{
requestData->logoCharacterWidth = readCachedUint32(requestData, FF_CACHE_FILE_WIDTH);
if(requestData->logoCharacterWidth == 0)
return false;
}
requestData->logoCharacterHeight = instance->config.logoHeight;
if(requestData->logoCharacterHeight == 0)
{
requestData->logoCharacterHeight = readCachedUint32(requestData, FF_CACHE_FILE_HEIGHT);
if(requestData->logoCharacterHeight == 0)
return false;
}
int fd = -1;
if(requestData->type == FF_LOGO_TYPE_KITTY)
{
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_COMPRESSED);
if(fd == -1)
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_UNCOMPRESSED);
}
else
else if(requestData->type == FF_LOGO_TYPE_SIXEL)
fd = getCacheFD(requestData, FF_CACHE_FILE_SIXEL);
if(fd == -1)
@@ -314,48 +456,73 @@ static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
char buffer[32768];
ssize_t readBytes;
while((readBytes = read(fd, buffer, sizeof(buffer))) > 0)
(void) write(STDOUT_FILENO, buffer, (size_t) readBytes);
FF_UNUSED(write(STDOUT_FILENO, buffer, (size_t) readBytes));
close(fd);
finishPrinting(instance, requestData);
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
instance->state.logoHeight = requestData->logoCharacterHeight;
//Go to upper left corner
fputs("\033[9999999D", stdout);
printf("\033[%uA", instance->state.logoHeight);
return true;
}
static bool getTermInfo(struct winsize* winsize)
static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
{
if(requestData->type == FF_LOGO_TYPE_CHAFA)
return printCachedChars(instance, requestData);
else
return printCachedPixel(instance, requestData);
}
static bool getCharacterPixelDimensions(FFLogoRequestData* requestData)
{
struct winsize winsize;
//Initialize every member to 0, because it isn't guaranteed that every terminal sets them all
memset(winsize, 0, sizeof(struct winsize));
memset(&winsize, 0, sizeof(struct winsize));
ioctl(STDOUT_FILENO, TIOCGWINSZ, winsize);
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
if(winsize->ws_row == 0 || winsize->ws_col == 0)
ffGetTerminalResponse("\033[18t", 't', "\033[8;%hu;%hut", &winsize->ws_row, &winsize->ws_col);
if(winsize.ws_row == 0 || winsize.ws_col == 0)
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
if(winsize->ws_ypixel == 0 || winsize->ws_xpixel == 0)
ffGetTerminalResponse("\033[14t", 't', "\033[4;%hu;%hut", &winsize->ws_ypixel, &winsize->ws_xpixel);
if(winsize.ws_row == 0 || winsize.ws_col == 0)
return false;
return
winsize->ws_row > 0 &&
winsize->ws_col > 0 &&
winsize->ws_ypixel > 0 &&
winsize->ws_xpixel > 0;
if(winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0)
ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
requestData->characterPixelWidth = winsize.ws_xpixel / (double) winsize.ws_col;
requestData->characterPixelHeight = winsize.ws_ypixel / (double) winsize.ws_row;
return requestData->characterPixelWidth > 1.0 && requestData->characterPixelHeight > 1.0;
}
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
//Performance optimisation
#ifndef FF_HAVE_CHAFA
if(type == FF_LOGO_TYPE_CHAFA)
return false;
#endif
FFLogoRequestData requestData;
if(!getTermInfo(&requestData.winsize))
return false;
requestData.type = type;
requestData.characterPixelWidth = requestData.winsize.ws_xpixel / (double) requestData.winsize.ws_col;
requestData.characterPixelHeight = requestData.winsize.ws_ypixel / (double) requestData.winsize.ws_row;
requestData.imagePixelWidth = (uint32_t) (instance->config.logoWidth * requestData.characterPixelWidth);
if(requestData.imagePixelWidth < 1)
requestData.characterPixelWidth = 1;
requestData.characterPixelHeight = 1;
if(
(type != FF_LOGO_TYPE_CHAFA || instance->config.logoWidth == 0 || instance->config.logoHeight == 0) &&
!getCharacterPixelDimensions(&requestData)
)
return false;
requestData.logoPixelWidth = simpleCeil((double) instance->config.logoWidth * requestData.characterPixelWidth);
requestData.logoPixelHeight = simpleCeil((double) instance->config.logoHeight * requestData.characterPixelHeight);
ffStrbufInitA(&requestData.cacheDir, PATH_MAX * 2);
ffStrbufAppend(&requestData.cacheDir, &instance->state.cacheDir);
ffStrbufAppendS(&requestData.cacheDir, "images");
@@ -371,7 +538,9 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
if(!ffStrbufEndsWithC(&requestData.cacheDir, '/'))
ffStrbufAppendC(&requestData.cacheDir, '/');
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.imagePixelWidth);
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.logoPixelWidth);
ffStrbufAppendC(&requestData.cacheDir, '*');
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.logoPixelHeight);
ffStrbufAppendC(&requestData.cacheDir, '/');
if(!instance->config.recache && printCached(instance, &requestData))
@@ -398,7 +567,7 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
#else //FF_HAVE_IMAGEMAGICK{6, 7}
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
FF_UNUSED(instance);
FF_UNUSED(instance, type);
return false;
}
#endif //FF_HAVE_IMAGEMAGICK{6, 7}
+7 -7
View File
@@ -3,12 +3,10 @@
#ifndef FF_INCLUDED_LOGO_SIXEL_sixel
#define FF_INCLUDED_LOGO_SIXEL_sixel
#include "fastfetch.h"
#include "../logo.h"
#if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6)
#include <sys/ioctl.h>
#define MAGICKCORE_HDRI_ENABLE 1
#define MAGICKCORE_QUANTUM_DEPTH 16
@@ -24,11 +22,14 @@ typedef struct FFLogoRequestData
FFLogoType type;
FFstrbuf cacheDir;
struct winsize winsize;
double characterPixelWidth;
double characterPixelHeight;
uint32_t imagePixelWidth;
uint32_t imagePixelHeight;
uint32_t logoPixelWidth;
uint32_t logoPixelHeight;
uint32_t logoCharacterHeight;
uint32_t logoCharacterWidth;
} FFLogoRequestData;
typedef struct FFIMData
@@ -50,5 +51,4 @@ FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoRequestData* r
FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoRequestData* requestData);
#endif
#endif
+230 -73
View File
@@ -1,8 +1,9 @@
#include "logo.h"
#include <ctype.h>
#include <string.h>
void ffLogoPrint(FFinstance* instance, const char* data, bool doColorReplacement)
void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement)
{
uint32_t currentlineLength = 0;
@@ -145,112 +146,268 @@ void ffLogoPrint(FFinstance* instance, const char* data, bool doColorReplacement
printf("\033[%uA", instance->state.logoHeight);
}
static void logoPrintFile(FFinstance* instance, bool doColorReplacement)
static void logoApplyMainColor(FFinstance* instance, const FFlogo* logo)
{
if(instance->config.mainColor.length == 0)
ffStrbufAppendS(&instance->config.mainColor, logo->builtinColors[0]);
}
static bool logoHasName(const FFlogo* logo, const char* name)
{
const char** logoName = logo->names;
while(*logoName != NULL)
{
if(strcasecmp(*logoName, name) == 0)
return true;
++logoName;
}
return false;
}
static const FFlogo* logoGetBuiltin(const char* name)
{
GetLogoMethod* methods = ffLogoBuiltinGetAll();
while(*methods != NULL)
{
const FFlogo* logo = (*methods)();
if(logoHasName(logo, name))
return logo;
++methods;
}
return NULL;
}
static const FFlogo* logoGetBuiltinDetected(FFinstance* instance)
{
const FFOSResult* os = ffDetectOS(instance);
const FFlogo* logo = logoGetBuiltin(os->id.chars);
if(logo != NULL)
return logo;
logo = logoGetBuiltin(os->name.chars);
if(logo != NULL)
return logo;
logo = logoGetBuiltin(os->prettyName.chars);
if(logo != NULL)
return logo;
logo = logoGetBuiltin(os->idLike.chars);
if(logo != NULL)
return logo;
logo = logoGetBuiltin(os->systemName.chars);
if(logo != NULL)
return logo;
return ffLogoBuiltinGetUnknown();
}
static inline void logoApplyMainColorDetected(FFinstance* instance)
{
logoApplyMainColor(instance, logoGetBuiltinDetected(instance));
}
static void logoPrintStruct(FFinstance* instance, const FFlogo* logo)
{
logoApplyMainColor(instance, logo);
const char** colors = logo->builtinColors;
for(int i = 0; *colors != NULL && i < FASTFETCH_LOGO_MAX_COLORS; i++, colors++)
{
if(instance->config.logoColors[i].length == 0)
ffStrbufAppendS(&instance->config.logoColors[i], *colors);
}
ffLogoPrintChars(instance, logo->data, true);
}
static bool logoPrintBuiltinIfExists(FFinstance* instance, const char* name)
{
const FFlogo* logo = logoGetBuiltin(name);
if(logo == NULL)
return false;
logoPrintStruct(instance, logo);
return true;
}
static inline void logoPrintDetected(FFinstance* instance)
{
logoPrintStruct(instance, logoGetBuiltinDetected(instance));
}
static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement)
{
FFstrbuf content;
ffStrbufInitA(&content, 2047);
if(ffAppendFileContent(instance->config.logoSource.chars, &content))
ffLogoPrint(instance, content.chars, doColorReplacement);
else
ffLogoPrintUnknown(instance);
}
static void logoPrintDetected(FFinstance* instance)
{
if(instance->config.logoSource.length > 0)
if(!ffAppendFileContent(instance->config.logoSource.chars, &content))
{
if(
!ffLogoPrintBuiltinIfExists(instance) &&
!ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_KITTY)
) logoPrintFile(instance, true);
return;
ffStrbufDestroy(&content);
return false;
}
ffLogoPrintBuiltinDetected(instance);
logoApplyMainColorDetected(instance);
ffLogoPrintChars(instance, content.chars, doColorReplacement);
ffStrbufDestroy(&content);
return true;
}
void ffPrintLogo(FFinstance* instance)
static bool logoPrintImageIfExists(FFinstance* instance, FFLogoType logoType)
{
if(instance->config.mainColor.length == 0)
ffLogoSetMainColor(instance);
if(!ffLogoPrintImageIfExists(instance, logoType))
return false;
if(( //Logo type needs set logo name, but nothing was given. Print question mark
instance->config.logoType == FF_LOGO_TYPE_BUILTIN ||
instance->config.logoType == FF_LOGO_TYPE_FILE ||
instance->config.logoType == FF_LOGO_TYPE_RAW ||
instance->config.logoType == FF_LOGO_TYPE_SIXEL
) && instance->config.logoSource.length == 0)
ffLogoPrintUnknown(instance);
else if(instance->config.logoType == FF_LOGO_TYPE_BUILTIN)
{
if(!ffLogoPrintBuiltinIfExists(instance))
ffLogoPrintUnknown(instance);
}
logoApplyMainColorDetected(instance);
return true;
}
static void logoPrintKnownType(FFinstance* instance)
{
bool successfull;
if(instance->config.logoType == FF_LOGO_TYPE_BUILTIN)
successfull = logoPrintBuiltinIfExists(instance, instance->config.logoSource.chars);
else if(instance->config.logoType == FF_LOGO_TYPE_FILE)
logoPrintFile(instance, true);
successfull = logoPrintFileIfExists(instance, true);
else if(instance->config.logoType == FF_LOGO_TYPE_RAW)
logoPrintFile(instance, false);
else if(instance->config.logoType == FF_LOGO_TYPE_SIXEL || instance->config.logoType == FF_LOGO_TYPE_KITTY)
{
if(!ffLogoPrintImageIfExists(instance, instance->config.logoType))
ffLogoPrintBuiltinDetected(instance);
}
else
successfull = logoPrintFileIfExists(instance, false);
else //image
successfull = logoPrintImageIfExists(instance, instance->config.logoType);
if(!successfull)
logoPrintDetected(instance);
}
static inline void printLogoWidth(const FFinstance* instance)
void ffLogoPrint(FFinstance* instance)
{
//In pipe mode, we don't have a logo or padding.
//We also don't need to set main color, because it won't be printed anyway.
//So we can return quickly here.
if(instance->config.pipe)
{
instance->state.logoHeight = 0;
instance->state.logoWidth = 0;
return;
}
//If the source is not set, we can directly print the detected logo.
if(instance->config.logoSource.length == 0)
{
logoPrintDetected(instance);
return;
}
//If the source and source type is set to something else than auto, always print with the set type.
if(instance->config.logoSource.length > 0 && instance->config.logoType != FF_LOGO_TYPE_AUTO)
{
logoPrintKnownType(instance);
return;
}
//If source matches the name of a builtin logo, print it and return.
if(logoPrintBuiltinIfExists(instance, instance->config.logoSource.chars))
return;
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell(instance);
//Terminal emulators that support kitty graphics protocol.
bool supportsKitty =
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0;
//Try to load the logo as an image. If it succeeds, print it and return.
if(logoPrintImageIfExists(instance, supportsKitty ? FF_LOGO_TYPE_KITTY : FF_LOGO_TYPE_CHAFA))
return;
//Try to load the logo as a file. If it succeeds, print it and return.
if(logoPrintFileIfExists(instance, true))
return;
logoPrintDetected(instance);
}
void ffLogoPrintLine(FFinstance* instance)
{
if(instance->state.logoWidth > 0)
printf("\033[%uC", instance->state.logoWidth);
++instance->state.keysHeight;
}
void ffPrintRemainingLogo(FFinstance* instance)
void ffLogoPrintRemaining(FFinstance* instance)
{
if(!instance->config.logoPrintRemaining)
return;
for(uint32_t i = instance->state.keysHeight; i <= instance->state.logoHeight; i++)
while(instance->state.keysHeight <= instance->state.logoHeight)
{
printLogoWidth(instance);
ffLogoPrintLine(instance);
putchar('\n');
}
}
void ffPrintLogoLine(FFinstance* instance)
void ffLogoBuiltinPrint(FFinstance* instance)
{
printLogoWidth(instance);
++instance->state.keysHeight;
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
GetLogoMethod* methods = ffLogoBuiltinGetAll();
while(*methods != NULL)
{
const FFlogo* logo = (*methods)();
printf("\033[%sm%s:\033[0m\n", logo->builtinColors[0], logo->names[0]);
logoPrintStruct(instance, logo);
ffLogoPrintRemaining(instance);
//reset everything
instance->state.logoHeight = 0;
instance->state.keysHeight = 0;
for(uint8_t i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
ffStrbufClear(&instance->config.logoColors[i]);
puts("\n");
++methods;
}
}
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
void ffLogoBuiltinList()
{
ffPrintLogoLine(instance);
GetLogoMethod* methods = ffLogoBuiltinGetAll();
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
ffPrintColor(&instance->config.mainColor);
uint32_t counter = 0;
if(customKeyFormat == NULL || customKeyFormat->length == 0)
while(*methods != NULL)
{
fputs(moduleName, stdout);
const FFlogo* logo = (*methods)();
const char** names = logo->names;
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);
}
printf("%u)%s ", counter, counter < 10 ? " " : "");
++counter;
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
ffStrbufWriteTo(&instance->config.separator, stdout);
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
while(*names != NULL)
{
printf("\"%s\" ", *names);
++names;
}
putchar('\n');
++methods;
}
}
void ffLogoBuiltinListAutocompletion()
{
GetLogoMethod* methods = ffLogoBuiltinGetAll();
while(*methods != NULL)
{
printf("%s\n", (*methods)()->names[0]);
++methods;
}
}
+13 -7
View File
@@ -5,17 +5,23 @@
#include "fastfetch.h"
typedef struct FFlogo
{
const char* data;
const char** names; //Null terminated
const char** builtinColors; //Null terminated
} FFlogo;
typedef const FFlogo*(*GetLogoMethod)();
//logo.c
void ffLogoPrint(FFinstance* instance, const char* data, bool doColorReplacement);
void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement);
//builtin.c
void ffLogoSetMainColor(FFinstance* instance);
const FFlogo* ffLogoBuiltinGetUnknown();
GetLogoMethod* ffLogoBuiltinGetAll();
void ffLogoPrintUnknown(FFinstance* instance);
bool ffLogoPrintBuiltinIfExists(FFinstance* instance);
void ffLogoPrintBuiltinDetected(FFinstance* instance);
//sixel/image.c
//image/image.c
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type);
#endif
+5 -6
View File
@@ -1,6 +1,5 @@
#include "fastfetch.h"
#include <unistd.h>
#include <dirent.h>
#define FF_BATTERY_MODULE_NAME "Battery"
@@ -85,9 +84,9 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
static void printBattery(FFinstance* instance, const BatteryResult* result, uint8_t index)
{
if(instance->config.batteryFormat.length == 0)
if(instance->config.battery.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_BATTERY_MODULE_NAME, index, &instance->config.batteryKey);
ffPrintLogoAndKey(instance, FF_BATTERY_MODULE_NAME, index, &instance->config.battery.key);
bool showStatus =
result->status.length > 0 &&
@@ -114,7 +113,7 @@ static void printBattery(FFinstance* instance, const BatteryResult* result, uint
}
else
{
ffPrintFormatString(instance, FF_BATTERY_MODULE_NAME, index, &instance->config.batteryKey, &instance->config.batteryFormat, NULL, FF_BATTERY_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_BATTERY_MODULE_NAME, index, &instance->config.battery, FF_BATTERY_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->technology},
@@ -144,7 +143,7 @@ void ffPrintBattery(FFinstance* instance)
DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
{
ffPrintError(instance, FF_BATTERY_MODULE_NAME, 0, &instance->config.batteryKey, &instance->config.batteryFormat, FF_BATTERY_NUM_FORMAT_ARGS, "opendir(\"%s\") == NULL", baseDir.chars);
ffPrintError(instance, FF_BATTERY_MODULE_NAME, 0, &instance->config.battery, "opendir(\"%s\") == NULL", baseDir.chars);
ffStrbufDestroy(&baseDir);
return;
}
@@ -175,7 +174,7 @@ void ffPrintBattery(FFinstance* instance)
}
if(results.length == 0)
ffPrintError(instance, FF_BATTERY_MODULE_NAME, 0, &instance->config.batteryKey, &instance->config.batteryFormat, FF_BATTERY_NUM_FORMAT_ARGS, "%s doesn't contain any battery folder", baseDir.chars);
ffPrintError(instance, FF_BATTERY_MODULE_NAME, 0, &instance->config.battery, "%s doesn't contain any battery folder", baseDir.chars);
ffListDestroy(&results);
ffStrbufDestroy(&baseDir);
+1 -1
View File
@@ -2,6 +2,6 @@
void ffPrintBreak(FFinstance* instance)
{
ffPrintLogoLine(instance);
ffLogoPrintLine(instance);
putchar('\n');
}
+11 -2
View File
@@ -2,7 +2,16 @@
void ffPrintColors(FFinstance* instance)
{
ffPrintLogoLine(instance);
if(instance->config.pipe)
{
ffLogoPrintLine(instance);
puts("████████████████████████");
ffLogoPrintLine(instance);
puts("████████████████████████");
return;
}
ffLogoPrintLine(instance);
// 4%d: Set the background color
// 3%d: Set the foreground color
@@ -11,7 +20,7 @@ void ffPrintColors(FFinstance* instance)
puts(FASTFETCH_TEXT_MODIFIER_RESET);
ffPrintLogoLine(instance);
ffLogoPrintLine(instance);
// 1: Set everything to bolt. This causes normal colors on some systems to be bright.
// 4%d: Set the backgound to the not bright color
+41 -21
View File
@@ -1,21 +1,9 @@
#include "fastfetch.h"
#include <string.h>
#include <stdlib.h>
#define FF_CPU_MODULE_NAME "CPU"
#define FF_CPU_NUM_FORMAT_ARGS 14
static double parseHz(FFstrbuf* content)
{
if(content->length == 0)
return 0;
double herz;
if(sscanf(content->chars, "%lf", &herz) != 1)
return 0;
return herz;
}
#define FF_CPU_NUM_FORMAT_ARGS 15
static double getGhz(const char* policyFile, const char* cpuFile)
{
@@ -26,23 +14,45 @@ static double getGhz(const char* policyFile, const char* cpuFile)
if(content.length == 0)
ffGetFileContent(cpuFile, &content);
double herz = parseHz(&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 detectCPUTemp(const FFinstance* instance)
{
const FFTempsResult *temps = ffDetectTemps(instance);
for(uint32_t i = 0; i < temps->values.length; i++)
{
FFTempValue* value = ffListGet(&temps->values, i);
if(
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
ffStrbufCompS(&value->name, "coretemp") == 0
) return value->value;
}
return 0.0 / 0.0; //NaN
}
void ffPrintCPU(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpuKey, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS))
if(ffPrintFromCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpu, FF_CPU_NUM_FORMAT_ARGS))
return;
FILE* cpuinfo = fopen(FASTFETCH_TARGET_DIR_ROOT"/proc/cpuinfo", "r");
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
{
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpuKey, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS, "fopen(\""FASTFETCH_TARGET_DIR_ROOT"/proc/cpuinfo\", \"r\") == NULL");
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpu, "fopen(\"""/proc/cpuinfo\", \"r\") == NULL");
return;
}
@@ -81,7 +91,12 @@ void ffPrintCPU(FFinstance* instance)
fclose(cpuinfo);
double procGhz = parseHz(&procGhzString) / 1000.0; //to GHz
double procGhz = ffStrbufToDouble(&procGhzString);
if(procGhz != procGhz)
procGhz = 0; //NaN
else
procGhz /= 1000.0; //To GHz
ffStrbufDestroy(&procGhzString);
double biosLimit = getGhz("/sys/devices/system/cpu/cpufreq/policy0/bios_limit", "/sys/devices/system/cpu/cpu0/cpufreq/bios_limit");
@@ -124,7 +139,7 @@ void ffPrintCPU(FFinstance* instance)
) {
ffStrbufDestroy(&name);
ffStrbufDestroy(&vendor);
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpuKey, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS, "No CPU info found in /proc/cpuinfo");
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpu, "No CPU info found in /proc/cpuinfo");
return;
}
@@ -143,6 +158,10 @@ void ffPrintCPU(FFinstance* instance)
ffStrbufSubstrBeforeFirstC(&namePretty, '@'); //Cut the speed output in the name as we append our own
ffStrbufTrimRight(&namePretty, ' '); //If we removed the @ in previous step there was most likely a space before it
double cpuTemp;
if(instance->config.cpu.outputFormat.length > 0)
cpuTemp = detectCPUTemp(instance);
FFstrbuf cpu;
ffStrbufInitA(&cpu, 128);
@@ -164,7 +183,7 @@ void ffPrintCPU(FFinstance* instance)
if(ghz > 0)
ffStrbufAppendF(&cpu, " @ %.9gGHz", ghz);
ffPrintAndWriteToCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpuKey, &cpu, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintAndWriteToCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpu, &cpu, FF_CPU_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &name},
{FF_FORMAT_ARG_TYPE_STRBUF, &namePretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &vendor},
@@ -172,6 +191,7 @@ void ffPrintCPU(FFinstance* instance)
{FF_FORMAT_ARG_TYPE_INT, &numProcsAvailable},
{FF_FORMAT_ARG_TYPE_INT, &physicalCores},
{FF_FORMAT_ARG_TYPE_INT, &numProcs},
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpuTemp},
{FF_FORMAT_ARG_TYPE_DOUBLE, &biosLimit},
{FF_FORMAT_ARG_TYPE_DOUBLE, &scalingMaxFreq},
{FF_FORMAT_ARG_TYPE_DOUBLE, &scalingMinFreq},
+5 -6
View File
@@ -1,6 +1,5 @@
#include "fastfetch.h"
#include <stdio.h>
#include <unistd.h>
#define FF_CPU_USAGE_MODULE_NAME "CPU Usage"
@@ -9,10 +8,10 @@
void ffPrintCPUUsage(FFinstance* instance)
{
long user, nice, system, idle, iowait, irq, softirq;
FILE* procStat = fopen(FASTFETCH_TARGET_DIR_ROOT"/proc/stat", "r");
FILE* procStat = fopen("/proc/stat", "r");
if(procStat == NULL)
{
ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsageKey, &instance->config.cpuUsageFormat, FF_CPU_USAGE_NUM_FORMAT_ARGS, "fopen(\""FASTFETCH_TARGET_DIR_ROOT"/proc/stat\", \"r\") == NULL");
ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "fopen(\"""/proc/stat\", \"r\") == NULL");
return;
}
if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) goto exit;
@@ -31,15 +30,15 @@ void ffPrintCPUUsage(FFinstance* instance)
long totalOverPeriod = totalJiffies2 - totalJiffies1;
double cpuPercent = (double)workOverPeriod / (double)totalOverPeriod * 100;
if(instance->config.cpuUsageFormat.length == 0)
if(instance->config.cpuUsage.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsageKey);
ffPrintLogoAndKey(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsage.key);
printf("%.2lf%%\n", cpuPercent);
}
else
{
ffPrintFormatString(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsageKey, &instance->config.cpuUsageFormat, NULL, FF_CPU_USAGE_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsage, FF_CPU_USAGE_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpuPercent}
});
}
+16 -8
View File
@@ -1,5 +1,7 @@
#include "fastfetch.h"
#include <stdlib.h>
#define FF_CURSOR_MODULE_NAME "Cursor"
#define FF_CURSOR_NUM_FORMAT_ARGS 2
@@ -12,9 +14,9 @@ static void printCursor(FFinstance* instance, FFstrbuf* cursorTheme, const FFstr
if(cursorTheme->length == 0)
ffStrbufAppendS(cursorTheme, "default");
if(instance->config.cursorFormat.length == 0)
if(instance->config.cursor.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey);
ffPrintLogoAndKey(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor.key);
ffStrbufWriteTo(cursorTheme, stdout);
if(cursorSize != NULL && cursorSize->length > 0)
@@ -28,7 +30,7 @@ static void printCursor(FFinstance* instance, FFstrbuf* cursorTheme, const FFstr
}
else
{
ffPrintFormatString(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, NULL, FF_CURSOR_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, FF_CURSOR_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, cursorTheme},
{FF_FORMAT_ARG_TYPE_STRBUF, cursorSize}
});
@@ -47,7 +49,7 @@ static void printCursorGTK(FFinstance* instance)
if(gtk->cursor.length == 0)
{
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Couldn't detect GTK Cursor");
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Couldn't detect GTK Cursor");
return;
}
@@ -69,7 +71,7 @@ static void printCursorXFCE(FFinstance* instance)
if(cursorTheme.length == 0)
{
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Couldn't find xfce cursor in xfconf (xsettings::/Gtk/CursorThemeName)");
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Couldn't find xfce cursor in xfconf (xsettings::/Gtk/CursorThemeName)");
return;
}
@@ -105,7 +107,7 @@ static void printCursorFromConfigFile(FFinstance* instance, const char* relative
}
if(cursorTheme.length == 0)
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Couldn't find cursor in %s", relativeFilePath);
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Couldn't find cursor in %s", relativeFilePath);
else
printCursor(instance, &cursorTheme, &cursorSize);
@@ -185,15 +187,21 @@ static bool printCursorFromEnv(FFinstance* instance)
void ffPrintCursor(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Cursor detection is not supported on Android");
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor detection is not supported on Android");
return;
#endif
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0)
{
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "WSLg uses native windows cursor");
return;
}
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
{
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Cursor isn't supported in TTY");
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor isn't supported in TTY");
return;
}
+3 -3
View File
@@ -4,14 +4,14 @@
void ffPrintDate(FFinstance* instance)
{
if(instance->config.dateFormat.length > 0)
if(instance->config.date.outputFormat.length > 0)
{
ffPrintDateTimeFormat(instance, FF_DATE_MODULE_NAME, &instance->config.dateKey, &instance->config.dateFormat);
ffPrintDateTimeFormat(instance, FF_DATE_MODULE_NAME, &instance->config.date);
return;
}
const FFDateTimeResult* datetime = ffDetectDateTime(instance);
ffPrintLogoAndKey(instance, FF_DATE_MODULE_NAME, 0, &instance->config.dateKey);
ffPrintLogoAndKey(instance, FF_DATE_MODULE_NAME, 0, &instance->config.date.key);
//yyyy-mm-dd
printf("%u-%s-%u\n", datetime->year, datetime->monthPretty.chars, datetime->dayInMonth);
+5 -5
View File
@@ -3,10 +3,10 @@
#define FF_DATETIME_MODULE_NAME "Date & Time"
#define FF_DATETIME_NUM_FORMAT_ARGS 20
void ffPrintDateTimeFormat(FFinstance* instance, const char* moduleName, const FFstrbuf* key, const FFstrbuf* format)
void ffPrintDateTimeFormat(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs)
{
const FFDateTimeResult* result = ffDetectDateTime(instance);
ffPrintFormatString(instance, moduleName, 0, key, format, NULL, FF_DATETIME_NUM_FORMAT_ARGS, (FFformatarg[]) {
ffPrintFormat(instance, moduleName, 0, moduleArgs, FF_DATETIME_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_UINT16, &result->year},
{FF_FORMAT_ARG_TYPE_UINT8, &result->yearShort},
{FF_FORMAT_ARG_TYPE_UINT8, &result->month},
@@ -32,14 +32,14 @@ void ffPrintDateTimeFormat(FFinstance* instance, const char* moduleName, const F
void ffPrintDateTime(FFinstance* instance)
{
if(instance->config.dateTimeFormat.length > 0)
if(instance->config.dateTime.outputFormat.length > 0)
{
ffPrintDateTimeFormat(instance, FF_DATETIME_MODULE_NAME, &instance->config.dateTimeKey, &instance->config.dateTimeFormat);
ffPrintDateTimeFormat(instance, FF_DATETIME_MODULE_NAME, &instance->config.dateTime);
return;
}
const FFDateTimeResult* datetime = ffDetectDateTime(instance);
ffPrintLogoAndKey(instance, FF_DATETIME_MODULE_NAME, 0, &instance->config.dateTimeKey);
ffPrintLogoAndKey(instance, FF_DATETIME_MODULE_NAME, 0, &instance->config.dateTime.key);
//yyyy-mm-dd hh:mm:ss
printf("%u-%s-%u %s:%s:%s\n", datetime->year, datetime->monthPretty.chars, datetime->dayInMonth, datetime->hourPretty.chars, datetime->minutePretty.chars, datetime->secondPretty.chars);
+5 -7
View File
@@ -1,14 +1,12 @@
#include "fastfetch.h"
#include <string.h>
#define FF_DE_MODULE_NAME "DE"
#define FF_DE_NUM_FORMAT_ARGS 3
void ffPrintDesktopEnvironment(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_DE_MODULE_NAME, 0, &instance->config.deKey, &instance->config.deFormat, FF_DE_NUM_FORMAT_ARGS, "DE detection is not supported on Android");
ffPrintError(instance, FF_DE_MODULE_NAME, 0, &instance->config.de, "DE detection is not supported on Android");
return;
#endif
@@ -16,13 +14,13 @@ void ffPrintDesktopEnvironment(FFinstance* instance)
if(result->dePrettyName.length == 0)
{
ffPrintError(instance, FF_DE_MODULE_NAME, 0, &instance->config.deKey, &instance->config.deFormat, FF_DE_NUM_FORMAT_ARGS, "No DE found");
ffPrintError(instance, FF_DE_MODULE_NAME, 0, &instance->config.de, "No DE found");
return;
}
if(instance->config.deFormat.length == 0)
if(instance->config.de.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_DE_MODULE_NAME, 0, &instance->config.deKey);
ffPrintLogoAndKey(instance, FF_DE_MODULE_NAME, 0, &instance->config.de.key);
ffStrbufWriteTo(&result->dePrettyName, stdout);
@@ -36,7 +34,7 @@ void ffPrintDesktopEnvironment(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_DE_MODULE_NAME, 0, &instance->config.deKey, &instance->config.deFormat, NULL, FF_DE_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_DE_MODULE_NAME, 0, &instance->config.de, FF_DE_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->deProcessName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->dePrettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->deVersion}
+9 -9
View File
@@ -7,7 +7,7 @@
static void getKey(FFinstance* instance, FFstrbuf* key, const char* folderPath, bool showFolderPath)
{
if(instance->config.diskKey.length == 0)
if(instance->config.disk.key.length == 0)
{
if(showFolderPath)
ffStrbufAppendF(key, FF_DISK_MODULE_NAME" (%s)", folderPath);
@@ -16,7 +16,7 @@ static void getKey(FFinstance* instance, FFstrbuf* key, const char* folderPath,
}
else
{
ffParseFormatString(key, &instance->config.diskKey, NULL, 1, (FFformatarg[]){
ffParseFormatString(key, &instance->config.disk.key, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, folderPath}
});
}
@@ -33,14 +33,14 @@ static void printStatvfs(FFinstance* instance, FFstrbuf* key, struct statvfs* fs
uint32_t files = (uint32_t) (fs->f_files - fs->f_ffree);
if(instance->config.diskFormat.length == 0)
if(instance->config.disk.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, key->chars, 0, NULL);
printf("%uGB / %uGB (%u%%)\n", used, total, percentage);
printf("%uGiB / %uGiB (%u%%)\n", used, total, percentage);
}
else
{
ffPrintFormatString(instance, key->chars, 0, NULL, &instance->config.diskFormat, NULL, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormatString(instance, key->chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &used},
{FF_FORMAT_ARG_TYPE_UINT, &total},
{FF_FORMAT_ARG_TYPE_UINT, &files},
@@ -64,9 +64,9 @@ static void printFolder(FFinstance* instance, const char* folderPath)
struct statvfs fs;
int ret = statvfs(folderPath, &fs);
if(ret != 0 && instance->config.diskFormat.length == 0)
if(ret != 0 && instance->config.disk.outputFormat.length == 0)
{
ffPrintError(instance, key.chars, 0, NULL, &instance->config.diskFormat, FF_DISK_NUM_FORMAT_ARGS, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
ffStrbufDestroy(&key);
return;
}
@@ -89,7 +89,7 @@ void ffPrintDisk(FFinstance* instance)
{
FF_STRBUF_CREATE(key);
getKey(instance, &key, "", false);
ffPrintError(instance, key.chars, 0, NULL, &instance->config.diskFormat, FF_DISK_NUM_FORMAT_ARGS, "statvfs failed for both / and " FASTFETCH_TARGET_DIR_HOME);
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs failed for both / and " FASTFETCH_TARGET_DIR_HOME);
ffStrbufDestroy(&key);
return;
}
@@ -108,7 +108,7 @@ void ffPrintDisk(FFinstance* instance)
{
FF_STRBUF_CREATE(key);
getKey(instance, &key, "", false);
ffPrintError(instance, key.chars, 0, NULL, &instance->config.diskFormat, FF_DISK_NUM_FORMAT_ARGS, "Custom disk folders string doesn't contain any folders");
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "Custom disk folders string doesn't contain any folders");
ffStrbufDestroy(&key);
return;
}
+6 -6
View File
@@ -6,7 +6,7 @@
void ffPrintFont(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.fontKey, &instance->config.fontFormat, FF_FONT_NUM_FORMAT_ARGS, "Font detection is not supported on Android");
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "Font detection is not supported on Android");
return;
#endif
@@ -14,7 +14,7 @@ void ffPrintFont(FFinstance* instance)
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
{
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.fontKey, &instance->config.fontFormat, FF_FONT_NUM_FORMAT_ARGS, "Font isn't supported in TTY");
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "Font isn't supported in TTY");
return;
}
@@ -25,7 +25,7 @@ void ffPrintFont(FFinstance* instance)
if(plasmaRaw->length == 0 && gtk2Raw->length == 0 && gtk3Raw->length == 0 && gtk4Raw->length == 0)
{
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.fontKey, &instance->config.fontFormat, FF_FONT_NUM_FORMAT_ARGS, "No fonts found");
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "No fonts found");
return;
}
@@ -45,9 +45,9 @@ void ffPrintFont(FFinstance* instance)
ffStrbufInitA(&gtk, 64);
ffParseGTK(&gtk, &gtk2.pretty, &gtk3.pretty, &gtk4.pretty);
if(instance->config.fontFormat.length == 0)
if(instance->config.font.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_FONT_MODULE_NAME, 0, &instance->config.fontKey);
ffPrintLogoAndKey(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font.key);
if(plasma.pretty.length > 0)
{
ffStrbufWriteTo(&plasma.pretty, stdout);
@@ -60,7 +60,7 @@ void ffPrintFont(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_FONT_MODULE_NAME, 0, &instance->config.fontKey, &instance->config.fontFormat, NULL, FF_FONT_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, FF_FONT_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, plasmaRaw},
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma.name},
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma.size},
+153 -201
View File
@@ -1,185 +1,9 @@
#include "fastfetch.h"
#include <string.h>
#define FF_GPU_MODULE_NAME "GPU"
#define FF_GPU_NUM_FORMAT_ARGS 5
#define FF_GPU_NUM_FORMAT_ARGS 6
typedef struct GPUResult
{
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
} GPUResult;
#ifdef FF_HAVE_VULKAN
#include <vulkan/vulkan.h>
static void vulkanFillGPUs(FFinstance* instance, FFlist* results)
{
FF_LIBRARY_LOAD(vulkan, instance->config.libVulkan, , "libvulkan.so", 2)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkCreateInstance,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkDestroyInstance,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkEnumeratePhysicalDevices,)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetPhysicalDeviceProperties,)
//Some drivers (nvdc) print messages to stdout
//and thats the best way i found to disable that
ffSuppressIO(true);
const VkApplicationInfo applicationInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = FASTFETCH_PROJECT_NAME,
.applicationVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_VERSION_MAJOR, 0, 0),
.pEngineName = "vulkanPrintGPUs",
.engineVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_VERSION_MAJOR, 0, 0),
.apiVersion = VK_API_VERSION_1_0,
};
const VkInstanceCreateInfo instanceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = NULL,
.pApplicationInfo = &applicationInfo,
.enabledLayerCount = 0,
.ppEnabledLayerNames = NULL,
.enabledExtensionCount = 0,
.ppEnabledExtensionNames = NULL,
.flags = 0
};
VkInstance vkInstance;
if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS)
{
dlclose(vulkan);
ffSuppressIO(false);
return;
}
uint32_t physicalDeviceCount;
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
{
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return;
}
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
{
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return;
}
for(uint32_t i = 0; i < physicalDeviceCount; i++)
{
VkPhysicalDeviceProperties physicalDeviceProperties;
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties);
//We don't want softare rasterizers
if(physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
continue;
GPUResult* result = ffListAdd(results);
ffStrbufInit(&result->vendor);
ffStrbufInit(&result->name);
ffStrbufInit(&result->driver);
ffStrbufAppendS(&result->name, physicalDeviceProperties.deviceName);
}
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return;
}
#endif
#ifdef FF_HAVE_LIBPCI
#include <pci/pci.h>
#include <unistd.h>
//see https://github.com/pciutils/pciutils/blob/5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b/ls-kernel.c#L220
static void pciGetDriver(struct pci_dev* dev, FFstrbuf* driver, char*(*ffpci_get_param)(struct pci_access*, char*))
{
if(dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
return;
const char* base = ffpci_get_param(dev->access, "sysfs.path");
if(!ffStrSet(base))
return;
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, dev->domain, dev->bus, dev->dev, dev->func);
ffStrbufEnsureFree(driver, 1023);
ssize_t resultLength = readlink(path.chars, driver->chars, driver->allocated - 1); //-1 for null terminator
if(resultLength > 0)
{
driver->length = (uint32_t) resultLength;
driver->chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(driver, '/');
}
ffStrbufDestroy(&path);
}
static void pciFillGPUs(FFinstance* instance, FFlist* results)
{
FF_LIBRARY_LOAD(pci, instance->config.libPCI, , "libpci.so", 4)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc,)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init,)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus,)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info,)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name,)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_get_param,)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup,)
struct pci_access *pacc = ffpci_alloc();
ffpci_init(pacc);
ffpci_scan_bus(pacc);
struct pci_dev* dev;
for (dev=pacc->devices; dev; dev=dev->next)
{
ffpci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS);
char class[1024];
ffpci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class);
if(
strcasecmp("VGA compatible controller", class) == 0 ||
strcasecmp("3D controller", class) == 0 ||
strcasecmp("Display controller", class) == 0
) {
GPUResult* result = ffListAdd(results);
ffStrbufInitA(&result->vendor, 256);
ffpci_lookup_name(pacc, result->vendor.chars, (int) result->vendor.allocated -1, PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
ffStrbufRecalculateLength(&result->vendor);
ffStrbufInitA(&result->name, 256);
ffpci_lookup_name(pacc, result->name.chars, (int) result->name.allocated - 1, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
ffStrbufRecalculateLength(&result->name);
ffStrbufInit(&result->driver);
if(instance->config.gpuFormat.length > 0) //We only need it for the format string, so don't detect it if it isn't needed
pciGetDriver(dev, &result->driver, ffpci_get_param);
};
}
ffpci_cleanup(pacc);
dlclose(pci);
}
#endif
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, GPUResult* result)
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* result)
{
const char* vendorPretty;
if(ffStrbufIgnCaseCompS(&result->vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0)
@@ -207,12 +31,13 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
ffStrbufAppend(&gpu, &namePretty);
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpuKey, cache, &gpu, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->vendor},
{FF_FORMAT_ARG_TYPE_STRING, vendorPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &namePretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->driver},
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature}
});
ffStrbufDestroy(&result->vendor);
@@ -222,32 +47,159 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
ffStrbufDestroy(&namePretty);
}
void ffPrintGPU(FFinstance* instance)
static void printGPUList(FFinstance* instance, const FFlist* list)
{
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS))
return;
FFlist gpus;
ffListInitA(&gpus, sizeof(GPUResult), 4);
FFcache cache;
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
#ifdef FF_HAVE_LIBPCI
pciFillGPUs(instance, &gpus);
#endif
#ifdef FF_HAVE_VULKAN
if(gpus.length == 0)
vulkanFillGPUs(instance, &gpus);
#endif
for(uint8_t i = 0; i < (uint8_t) gpus.length; i++)
printGPUResult(instance, gpus.length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(&gpus, i));
if(gpus.length == 0)
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, "No GPUs found.");
for(uint8_t i = 0; i < (uint8_t) list->length; i++)
printGPUResult(instance, list->length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(list, i));
ffCacheClose(&cache);
ffListDestroy(&gpus);
}
#ifdef FF_HAVE_LIBPCI
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <pci/pci.h>
//see https://github.com/pciutils/pciutils/blob/5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b/ls-kernel.c#L220
static void pciGetDriver(struct pci_dev* dev, FFstrbuf* driver, char*(*ffpci_get_param)(struct pci_access*, char*))
{
if(dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
return;
const char* base = ffpci_get_param(dev->access, "sysfs.path");
if(!ffStrSet(base))
return;
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, dev->domain, dev->bus, dev->dev, dev->func);
ffStrbufEnsureFree(driver, 1023);
ssize_t resultLength = readlink(path.chars, driver->chars, driver->allocated - 1); //-1 for null terminator
if(resultLength > 0)
{
driver->length = (uint32_t) resultLength;
driver->chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(driver, '/');
}
ffStrbufDestroy(&path);
}
static double pciGetTemperatur(const FFinstance* instance, uint16_t deviceClass)
{
const FFTempsResult* tempsResult = ffDetectTemps(instance);
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 == deviceClass * 256)
return tempValue->value;
}
return 0.0 / 0.0; //NaN
}
static bool pciPrintGPUs(FFinstance* instance)
{
FF_LIBRARY_LOAD(pci, instance->config.libPCI, false, "libpci.so", 4)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_get_param, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup, false)
FFlist results;
ffListInit(&results, sizeof(FFGPUResult));
struct pci_access *pacc = ffpci_alloc();
ffpci_init(pacc);
ffpci_scan_bus(pacc);
struct pci_dev* dev;
for (dev=pacc->devices; dev; dev=dev->next)
{
ffpci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS);
char class[1024];
ffpci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class);
if(
strcasecmp("VGA compatible controller", class) == 0 ||
strcasecmp("3D controller", class) == 0 ||
strcasecmp("Display controller", class) == 0
) {
FFGPUResult* result = ffListAdd(&results);
ffStrbufInitA(&result->vendor, 256);
ffpci_lookup_name(pacc, result->vendor.chars, (int) ffStrbufGetFree(&result->vendor), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
ffStrbufRecalculateLength(&result->vendor);
ffStrbufInitA(&result->name, 256);
ffpci_lookup_name(pacc, result->name.chars, (int) ffStrbufGetFree(&result->name), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
ffStrbufRecalculateLength(&result->name);
ffStrbufInit(&result->driver);
result->temperature = 0;
//We only need it for the format string, so don't detect it if it isn't needed
if(instance->config.gpu.outputFormat.length > 0)
{
pciGetDriver(dev, &result->driver, ffpci_get_param);
result->temperature = pciGetTemperatur(instance, dev->device_class);
}
};
}
ffpci_cleanup(pacc);
dlclose(pci);
if(results.length == 0)
{
ffListDestroy(&results);
return false;
}
printGPUList(instance, &results);
ffListDestroy(&results);
return true;
}
#endif
static bool vulkanPrintGPUs(FFinstance* instance)
{
const FFVulkanResult* result = ffDetectVulkan(instance);
if(result->devices.length == 0)
return false;
printGPUList(instance, &result->devices);
return true;
}
void ffPrintGPU(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS))
return;
#ifdef FF_HAVE_LIBPCI
if(pciPrintGPUs(instance))
return;
#endif
if(vulkanPrintGPUs(instance))
return;
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found.");
}
+113 -52
View File
@@ -1,10 +1,15 @@
#include "fastfetch.h"
#include <ctype.h>
#include <stdlib.h>
#define FF_HOST_MODULE_NAME "Host"
#define FF_HOST_NUM_FORMAT_ARGS 3
#define FF_HOST_NUM_FORMAT_ARGS 15
#ifdef __ANDROID__
#include <ctype.h>
#endif
#ifndef __ANDROID__
static bool hostValueSet(FFstrbuf* value)
{
ffStrbufTrimRight(value, '\n');
@@ -32,7 +37,6 @@ static bool hostValueSet(FFstrbuf* value)
;
}
#ifndef __ANDROID__
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffGetFileContent(devicesPath, buffer);
@@ -44,88 +48,145 @@ static void getHostValue(const char* devicesPath, const char* classPath, FFstrbu
void ffPrintHost(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_HOST_MODULE_NAME, &instance->config.hostKey, &instance->config.hostFormat, FF_HOST_NUM_FORMAT_ARGS))
if(ffPrintFromCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, FF_HOST_NUM_FORMAT_ARGS))
return;
FFstrbuf family;
ffStrbufInit(&family);
FFstrbuf product_family;
ffStrbufInit(&product_family);
#ifndef __ANDROID__
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &family);
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &product_family);
if(!hostValueSet(&product_family))
ffStrbufClear(&product_family);
#else
ffSettingsGetAndroidProperty("ro.product.device", &family);
ffSettingsGetAndroidProperty("ro.product.device", &product_family);
#endif
bool familySet = hostValueSet(&family);
FFstrbuf name;
ffStrbufInit(&name);
FFstrbuf product_name;
ffStrbufInit(&product_name);
#ifndef __ANDROID__
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &name);
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &product_name);
if(name.length == 0)
ffGetFileContent("/sys/firmware/devicetree/base/model", &name);
if(product_name.length == 0)
ffGetFileContent("/sys/firmware/devicetree/base/model", &product_name);
if(name.length == 0)
ffGetFileContent("/tmp/sysinfo/model", &name);
if(product_name.length == 0)
ffGetFileContent("/tmp/sysinfo/model", &product_name);
if(ffStrbufStartsWithS(&name, "Standard PC"))
if(ffStrbufStartsWithS(&product_name, "Standard PC"))
{
FFstrbuf copy;
ffStrbufInitCopy(&copy, &name);
ffStrbufSetS(&name, "KVM/QEMU ");
ffStrbufAppend(&name, &copy);
ffStrbufInitCopy(&copy, &product_name);
ffStrbufSetS(&product_name, "KVM/QEMU ");
ffStrbufAppend(&product_name, &copy);
ffStrbufDestroy(&copy);
}
if(!hostValueSet(&product_name))
ffStrbufClear(&product_name);
//On WSL, the real host can't be detected. Instead use WSL as host.
if(product_name.length == 0 && product_family.length == 0 && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
)) ffStrbufAppendS(&product_name, "Windows Subsystem for Linux");
#else
ffSettingsGetAndroidProperty("ro.product.brand", &name);
if(name.length > 0){
name.chars[0] = (char) toupper(name.chars[0]);
ffStrbufAppendC(&name, ' ');
ffSettingsGetAndroidProperty("ro.product.brand", &product_name);
if(product_name.length > 0){
product_name.chars[0] = (char) toupper(product_name.chars[0]);
ffStrbufAppendC(&product_name, ' ');
}
if(!ffSettingsGetAndroidProperty("ro.product.model", &name))
ffSettingsGetAndroidProperty("ro.product.name", &name);
if(!ffSettingsGetAndroidProperty("ro.product.model", &product_name))
ffSettingsGetAndroidProperty("ro.product.name", &product_name);
ffStrbufTrimRight(&name, ' ');
ffStrbufTrimRight(&product_name, ' ');
#endif
bool nameSet = hostValueSet(&name);
FFstrbuf version;
ffStrbufInit(&version);
#ifndef __ANDROID__
getHostValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &version);
#endif
bool versionSet = hostValueSet(&version);
if(!familySet && !nameSet)
if(product_family.length == 0 && product_name.length == 0)
{
ffStrbufDestroy(&family);
ffStrbufDestroy(&name);
ffStrbufDestroy(&version);
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.hostKey, &instance->config.hostFormat, FF_HOST_NUM_FORMAT_ARGS, "neither family nor name is set by O.E.M.");
ffStrbufDestroy(&product_family);
ffStrbufDestroy(&product_name);
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "neither product_family nor product_name is set by O.E.M.");
return;
}
#ifdef __ANDROID__
#define FF_HOST_DATA(name) \
FFstrbuf name; \
ffStrbufInitA(&name, 0);
#else
#define FF_HOST_DATA(name) \
FFstrbuf name; \
ffStrbufInit(&name); \
getHostValue("/sys/devices/virtual/dmi/id/"#name, "/sys/class/dmi/id/"#name, &name); \
if(!hostValueSet(&name)) \
ffStrbufClear(&name);
#endif
FF_HOST_DATA(product_version)
FF_HOST_DATA(product_sku)
FF_HOST_DATA(bios_date)
FF_HOST_DATA(bios_release)
FF_HOST_DATA(bios_vendor)
FF_HOST_DATA(bios_version)
FF_HOST_DATA(board_name)
FF_HOST_DATA(board_vendor)
FF_HOST_DATA(board_version)
FF_HOST_DATA(chassis_type)
FF_HOST_DATA(chassis_vendor)
FF_HOST_DATA(chassis_version)
FF_HOST_DATA(sys_vendor)
FFstrbuf host;
ffStrbufInit(&host);
if(nameSet)
ffStrbufAppend(&host, &name);
if(product_name.length > 0)
ffStrbufAppend(&host, &product_name);
else
ffStrbufAppend(&host, &family);
ffStrbufAppend(&host, &product_family);
if(versionSet)
if(product_version.length > 0)
{
ffStrbufAppendC(&host, ' ');
ffStrbufAppend(&host, &version);
ffStrbufAppend(&host, &product_version);
}
ffPrintAndWriteToCache(instance, FF_HOST_MODULE_NAME, &instance->config.hostKey, &host, &instance->config.hostFormat, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &family},
{FF_FORMAT_ARG_TYPE_STRBUF, &name},
{FF_FORMAT_ARG_TYPE_STRBUF, &version}
ffPrintAndWriteToCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, &host, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &product_family},
{FF_FORMAT_ARG_TYPE_STRBUF, &product_name},
{FF_FORMAT_ARG_TYPE_STRBUF, &product_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &product_sku},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_date},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_release},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &board_name},
{FF_FORMAT_ARG_TYPE_STRBUF, &board_vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &board_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_type},
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &sys_vendor}
});
ffStrbufDestroy(&family);
ffStrbufDestroy(&name);
ffStrbufDestroy(&version);
ffStrbufDestroy(&product_family);
ffStrbufDestroy(&product_name);
//On Android, all of them get initialized without heap, so no need to destroy them.
#ifndef __ANDROID__
ffStrbufDestroy(&product_version);
ffStrbufDestroy(&product_sku);
ffStrbufDestroy(&bios_date);
ffStrbufDestroy(&bios_release);
ffStrbufDestroy(&bios_vendor);
ffStrbufDestroy(&bios_version);
ffStrbufDestroy(&board_name);
ffStrbufDestroy(&board_vendor);
ffStrbufDestroy(&board_version);
ffStrbufDestroy(&chassis_type);
ffStrbufDestroy(&chassis_vendor);
ffStrbufDestroy(&chassis_version);
ffStrbufDestroy(&sys_vendor);
#endif
}
+6 -6
View File
@@ -6,7 +6,7 @@
void ffPrintIcons(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.iconsKey, &instance->config.iconsFormat, FF_ICONS_NUM_FORMAT_ARGS, "Icons detection is not supported on Android");
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons detection is not supported on Android");
return;
#endif
@@ -14,7 +14,7 @@ void ffPrintIcons(FFinstance* instance)
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
{
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.fontKey, &instance->config.fontFormat, FF_ICONS_NUM_FORMAT_ARGS, "Icons aren't supported in TTY");
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons aren't supported in TTY");
return;
}
@@ -25,16 +25,16 @@ void ffPrintIcons(FFinstance* instance)
if(plasma->length == 0 && gtk2->length == 0 && gtk3->length == 0 && gtk4->length == 0)
{
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.iconsKey, &instance->config.iconsFormat, FF_ICONS_NUM_FORMAT_ARGS, "No icons could be found");
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "No icons could be found");
return;
}
FF_STRBUF_CREATE(gtkPretty);
ffParseGTK(&gtkPretty, gtk2, gtk3, gtk4);
if(instance->config.iconsFormat.length == 0)
if(instance->config.icons.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.iconsKey);
ffPrintLogoAndKey(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons.key);
if(plasma->length > 0)
{
@@ -49,7 +49,7 @@ void ffPrintIcons(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.iconsKey, &instance->config.iconsFormat, NULL, FF_ICONS_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, FF_ICONS_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, plasma},
{FF_FORMAT_ARG_TYPE_STRBUF, gtk2},
{FF_FORMAT_ARG_TYPE_STRBUF, gtk3},
+3 -3
View File
@@ -5,14 +5,14 @@
void ffPrintKernel(FFinstance* instance)
{
if(instance->config.kernelFormat.length == 0)
if(instance->config.kernel.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernelKey);
ffPrintLogoAndKey(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel.key);
puts(instance->state.utsname.release);
}
else
{
ffPrintFormatString(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernelKey, &instance->config.kernelFormat, NULL, FF_KERNEL_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel, FF_KERNEL_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.sysname},
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.release},
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.version}
+19 -7
View File
@@ -1,5 +1,7 @@
#include "fastfetch.h"
#include <stdlib.h>
#define FF_LOCALE_MODULE_NAME "Locale"
#define FF_LOCALE_NUM_FORMAT_ARGS 1
@@ -22,24 +24,34 @@ static void getLocaleFromEnv(FFstrbuf* locale)
void ffPrintLocale(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_LOCALE_MODULE_NAME, &instance->config.localeKey, &instance->config.localeFormat, FF_LOCALE_NUM_FORMAT_ARGS))
if(ffPrintFromCache(instance, FF_LOCALE_MODULE_NAME, &instance->config.locale, FF_LOCALE_NUM_FORMAT_ARGS))
return;
FFstrbuf locale;
ffStrbufInit(&locale);
ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/locale.conf", "LANG =", &locale);
if (locale.length == 0)
getLocaleFromEnv(&locale);
//Ubuntu (and deriviates) use a non standard locale file.
//Parse it first, because on distributions where it exists, it takes precedence.
//Otherwise use the standard /etc/locale.conf file.
ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/default/locale", "LANG =", &locale);
if(locale.length == 0)
{
ffPrintError(instance, FF_LOCALE_MODULE_NAME, 0, &instance->config.localeKey, &instance->config.localeFormat, FF_LOCALE_NUM_FORMAT_ARGS, "No locale found");
ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/locale.conf", "LANG =", &locale);
}
if(locale.length == 0)
{
getLocaleFromEnv(&locale);
}
if(locale.length == 0)
{
ffPrintError(instance, FF_LOCALE_MODULE_NAME, 0, &instance->config.locale, "No locale found");
return;
}
ffPrintAndWriteToCache(instance, FF_LOCALE_MODULE_NAME, &instance->config.localeKey, &locale, &instance->config.localeFormat, FF_LOCALE_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintAndWriteToCache(instance, FF_LOCALE_MODULE_NAME, &instance->config.locale, &locale, FF_LOCALE_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &locale}
});
+17 -11
View File
@@ -3,29 +3,35 @@
#define FF_LOCALIP_MODULE_NAME "Local IP"
#define FF_LOCALIP_NUM_FORMAT_ARGS 1
#include <sys/types.h>
#include <string.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
static void printValue(FFinstance* instance, const char* ifaName, const char* addressBuffer)
{
FF_STRBUF_CREATE(key);
FFstrbuf key;
ffStrbufInit(&key);
if (instance->config.localIpKey.length == 0) {
if (instance->config.localIP.key.length == 0)
{
ffStrbufAppendF(&key, FF_LOCALIP_MODULE_NAME " (%s)", ifaName);
} else {
ffParseFormatString(&key, &instance->config.localIpKey, NULL, 1, (FFformatarg[]){
}
else
{
ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, ifaName}
});
}
if (instance->config.localIpFormat.length == 0) {
ffPrintLogoAndKey(instance, FF_LOCALIP_MODULE_NAME, 0, &key);
if (instance->config.localIP.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
puts(addressBuffer);
} else {
ffPrintFormatString(instance, FF_LOCALIP_MODULE_NAME, 0, &key, &instance->config.localIpFormat, NULL, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){
}
else
{
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, addressBuffer}
});
}
@@ -38,7 +44,7 @@ void ffPrintLocalIp(FFinstance* instance)
struct ifaddrs* ifAddrStruct = NULL;
int ret = getifaddrs(&ifAddrStruct);
if (ret < 0) {
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIpKey, &instance->config.localIpFormat, FF_LOCALIP_NUM_FORMAT_ARGS, "getifaddrs(&ifAddrStruct) < 0 (%i)", ret);
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "getifaddrs(&ifAddrStruct) < 0 (%i)", ret);
return;
}
+8 -6
View File
@@ -1,14 +1,16 @@
#include "fastfetch.h"
#include <stdlib.h>
#define FF_MEMORY_MODULE_NAME "Memory"
#define FF_MEMORY_NUM_FORMAT_ARGS 3
// Impl inspired by: https://github.com/sam-barr/paleofetch/blob/b7c58a52c0de39b53c9b5f417889a5886d324bfa/paleofetch.c#L544
void ffPrintMemory(FFinstance* instance)
{
FILE* meminfo = fopen(FASTFETCH_TARGET_DIR_ROOT"/proc/meminfo", "r");
FILE* meminfo = fopen("/proc/meminfo", "r");
if(meminfo == NULL) {
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, FF_MEMORY_NUM_FORMAT_ARGS, "fopen(\""FASTFETCH_TARGET_DIR_ROOT"/proc/meminfo\", \"r\") == NULL");
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "fopen(\"""/proc/meminfo\", \"r\") == NULL");
return;
}
@@ -42,18 +44,18 @@ void ffPrintMemory(FFinstance* instance)
if(used_mem == 0 && total_mem == 0 && percentage == 0)
{
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, FF_MEMORY_NUM_FORMAT_ARGS, FASTFETCH_TARGET_DIR_ROOT"/proc/meminfo could't be parsed");
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "/proc/meminfo could't be parsed");
return;
}
if(instance->config.memoryFormat.length == 0)
if(instance->config.memory.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey);
ffPrintLogoAndKey(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory.key);
printf("%uMiB / %uMiB (%u%%)\n", used_mem, total_mem, percentage);
}
else
{
ffPrintFormatString(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, NULL, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &used_mem},
{FF_FORMAT_ARG_TYPE_UINT, &total_mem},
{FF_FORMAT_ARG_TYPE_UINT8, &percentage}
+93
View File
@@ -0,0 +1,93 @@
#include "fastfetch.h"
#define FF_OPENCL_MODULE_NAME "OpenCL"
#define FF_OPENCL_NUM_FORMAT_ARGS 3
#ifdef FF_HAVE_OPENCL
#include <dlfcn.h>
#define CL_TARGET_OPENCL_VERSION 100
#include <CL/cl.h>
typedef struct OpenCLData
{
FF_LIBRARY_SYMBOL(clGetPlatformIDs);
FF_LIBRARY_SYMBOL(clGetDeviceIDs);
FF_LIBRARY_SYMBOL(clGetDeviceInfo);
} OpenCLData;
static const char* openCLHandelData(FFinstance* instance, OpenCLData* data)
{
cl_platform_id platformID;
cl_uint numPlatforms;
data->ffclGetPlatformIDs(1, &platformID, &numPlatforms);
if(numPlatforms == 0)
return "clGetPlatformIDs returned 0 platforms";
cl_device_id deviceID;
cl_uint numDevices;
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices);
if(numDevices == 0)
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 1, &deviceID, &numDevices);
if(numDevices == 0)
return "clGetDeviceIDs returned 0 devices";
char version[64];
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL);
if(!ffStrSet(version))
return "clGetDeviceInfo returned NULL or empty string";
char device[128];
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(device), device, NULL);
char vendor[32];
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL);
if(instance->config.openCL.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL.key);
puts(version);
}
else
{
ffPrintFormat(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, FF_OPENCL_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRING, version},
{FF_FORMAT_ARG_TYPE_STRING, device},
{FF_FORMAT_ARG_TYPE_STRING, vendor}
});
}
return NULL;
}
static const char* printOpenCL(FFinstance* instance)
{
OpenCLData data;
FF_LIBRARY_LOAD(opencl, instance->config.libOpenCL, "dlopen libOpenCL.so failed", "libOpenCL.so", 1);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(opencl, data.ffclGetPlatformIDs, clGetPlatformIDs, "dlsym clGetPlatformIDs failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(opencl, data.ffclGetDeviceIDs, clGetDeviceIDs, "dlsym clGetDeviceIDs failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(opencl, data.ffclGetDeviceInfo, clGetDeviceInfo, "dlsym clGetDeviceInfo failed");
const char* error = openCLHandelData(instance, &data);
dlclose(opencl);
return error;
}
#endif
void ffPrintOpenCL(FFinstance* instance)
{
const char* error;
#ifdef FF_HAVE_OPENCL
error = printOpenCL(instance);
#else
error = "Fastfetch was build without OpenCL support";
#endif
if(error != NULL)
ffPrintError(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, error);
}
+393
View File
@@ -0,0 +1,393 @@
#include "fastfetch.h"
#include <string.h>
#define FF_OPENGL_MODULE_NAME "OpenGL"
#define FF_OPENGL_NUM_FORMAT_ARGS 4
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
#define FF_HAVE_GL 1
#include <dlfcn.h>
#include <GL/gl.h>
#define FF_OPENGL_BUFFER_WIDTH 1
#define FF_OPENGL_BUFFER_HEIGHT 1
typedef struct GLData
{
FF_LIBRARY_SYMBOL(glGetString);
} GLData;
static const char* glHandlePrint(FFinstance* instance, const GLData* data)
{
const char* version = (const char*) data->ffglGetString(GL_VERSION);
if(!ffStrSet(version))
return "glGetString(GL_VERSION) returned NULL";
const char* renderer = (const char*) data->ffglGetString(GL_RENDERER);
const char* vendor = (const char*) data->ffglGetString(GL_VENDOR);
const char* slv = (const char*) data->ffglGetString(GL_SHADING_LANGUAGE_VERSION);
if(instance->config.openGL.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_OPENGL_MODULE_NAME, 0, &instance->config.openGL.key);
puts(version);
}
else
{
ffPrintFormat(instance, FF_OPENGL_MODULE_NAME, 0, &instance->config.openGL, FF_OPENGL_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRING, version},
{FF_FORMAT_ARG_TYPE_STRING, renderer},
{FF_FORMAT_ARG_TYPE_STRING, vendor},
{FF_FORMAT_ARG_TYPE_STRING, slv}
});
}
return NULL;
}
#ifdef FF_HAVE_EGL
#include <EGL/egl.h>
typedef struct EGLData
{
GLData glData;
FF_LIBRARY_SYMBOL(eglGetProcAddress);
FF_LIBRARY_SYMBOL(eglGetDisplay);
FF_LIBRARY_SYMBOL(eglInitialize);
FF_LIBRARY_SYMBOL(eglBindAPI);
FF_LIBRARY_SYMBOL(eglGetConfigs);
FF_LIBRARY_SYMBOL(eglCreatePbufferSurface);
FF_LIBRARY_SYMBOL(eglCreateContext);
FF_LIBRARY_SYMBOL(eglMakeCurrent);
FF_LIBRARY_SYMBOL(eglDestroyContext);
FF_LIBRARY_SYMBOL(eglDestroySurface);
FF_LIBRARY_SYMBOL(eglTerminate);
EGLDisplay display;
EGLConfig config;
EGLSurface surface;
EGLContext context;
} EGLData;
static const char* eglHandleContext(FFinstance* instance, EGLData* data)
{
if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE)
return "eglMakeCurrent returned EGL_FALSE";
return glHandlePrint(instance, &data->glData);
}
static const char* eglHandleSurface(FFinstance* instance, EGLData* data)
{
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
if(data->context == EGL_NO_CONTEXT)
return "eglCreateContext returned EGL_NO_CONTEXT";
const char* error = eglHandleContext(instance, data);
data->ffeglDestroyContext(data->display, data->context);
return error;
}
static const char* eglHandleDisplay(FFinstance* instance, EGLData* data)
{
if(data->ffeglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
return "eglBindAPI returned EGL_FALSE";
EGLint eglConfigCount;
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
if(eglConfigCount == 0)
return "eglGetConfigs returned 0 configs";
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
EGL_NONE
});
if(data->surface == EGL_NO_SURFACE)
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
const char* error = eglHandleSurface(instance, data);
data->ffeglDestroySurface(data->display, data->surface);
return error;
}
static const char* eglHandleData(FFinstance* instance, EGLData* data)
{
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffeglGetProcAddress("glGetString");
if(!data->glData.ffglGetString)
return "eglGetProcAddress(glGetString) returned NULL";
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
if(data->display == EGL_NO_DISPLAY)
return "eglGetDisplay returned EGL_NO_DISPLAY";
EGLint major, minor;
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
return "eglInitialize returned EGL_FALSE";
const char* error = eglHandleDisplay(instance, data);
data->ffeglTerminate(data->display);
return error;
}
static const char* eglPrint(FFinstance* instance)
{
EGLData eglData;
FF_LIBRARY_LOAD(egl, instance->config.libEGL, "dlopen egl failed", "libEGL.so", 1);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglGetProcAddress, eglGetProcAddress, "dlsym eglGetProcAddress failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglGetDisplay, eglGetDisplay, "dlsym eglGetDisplay failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglInitialize, eglInitialize, "dlsym eglInitialize failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglBindAPI, eglBindAPI, "dlsym eglBindAPI failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglGetConfigs, eglGetConfigs, "dlsym eglGetConfigs failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglCreatePbufferSurface, eglCreatePbufferSurface, "dlsym eglCreatePbufferSurface failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglCreateContext, eglCreateContext, "dlsym eglCreateContext failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglMakeCurrent, eglMakeCurrent, "dlsym eglMakeCurrent failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglDestroyContext, eglDestroyContext, "dlsym eglDestroyContext failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglDestroySurface, eglDestroySurface, "dlsym eglDestroySurface failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglTerminate, eglTerminate, "dlsym eglTerminate failed");
const char* error = eglHandleData(instance, &eglData);
dlclose(egl);
return error;
}
#endif //FF_HAVE_EGL
#ifdef FF_HAVE_GLX
#include <GL/glx.h>
typedef struct GLXData
{
GLData glData;
FF_LIBRARY_SYMBOL(glXGetProcAddress);
FF_LIBRARY_SYMBOL(XOpenDisplay);
FF_LIBRARY_SYMBOL(glXChooseVisual);
FF_LIBRARY_SYMBOL(XCreatePixmap);
FF_LIBRARY_SYMBOL(glXCreateGLXPixmap);
FF_LIBRARY_SYMBOL(glXCreateContext);
FF_LIBRARY_SYMBOL(glXMakeCurrent);
FF_LIBRARY_SYMBOL(glXDestroyContext);
FF_LIBRARY_SYMBOL(glXDestroyGLXPixmap);
FF_LIBRARY_SYMBOL(XFreePixmap);
FF_LIBRARY_SYMBOL(XCloseDisplay);
Display* display;
XVisualInfo* visualInfo;
Pixmap pixmap;
GLXPixmap glxPixmap;
GLXContext context;
} GLXData;
static const char* glxHandleContext(FFinstance* instance, GLXData* data)
{
if(data->ffglXMakeCurrent(data->display, data->glxPixmap, data->context) != True)
return "glXMakeCurrent returned False";
return glHandlePrint(instance, &data->glData);
}
static const char* glxHandleGLXPixmap(FFinstance* instance, GLXData* data)
{
data->context = data->ffglXCreateContext(data->display, data->visualInfo, NULL, True);
if(data->context == NULL)
return "glXCreateContext returned NULL";
const char* error = glxHandleContext(instance, data);
data->ffglXDestroyContext(data->display, data->context);
return error;
}
static const char* glxHandlePixmap(FFinstance* instance, GLXData* data)
{
data->glxPixmap = data->ffglXCreateGLXPixmap(data->display, data->visualInfo, data->pixmap);
if(data->glxPixmap == None)
return "glXCreateGLXPixmap returned None";
const char* error = glxHandleGLXPixmap(instance, data);
data->ffglXDestroyGLXPixmap(data->display, data->glxPixmap);
return error;
}
static const char* glxHandleVisualInfo(FFinstance* instance, GLXData* data)
{
data->pixmap = data->ffXCreatePixmap(data->display, DefaultRootWindow(data->display), FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, (unsigned int) data->visualInfo->depth);
if(data->pixmap == None)
return "XCreatePixmap returned None";
const char* error = glxHandlePixmap(instance, data);
data->ffXFreePixmap(data->display, data->pixmap);
return error;
}
static const char* glxHandleDisplay(FFinstance* instance, GLXData* data)
{
data->visualInfo = data->ffglXChooseVisual(data->display, DefaultScreen(data->display), (int[]){None});
if(data->visualInfo == NULL)
return "glXChooseVisual returned NULL";
return glxHandleVisualInfo(instance, data);
}
static const char* glxHandleData(FFinstance* instance, GLXData* data)
{
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
if(data->glData.ffglGetString == NULL)
return "glXGetProcAddress(glGetString) returned NULL";
data->display = data->ffXOpenDisplay(NULL);
if(data->display == NULL)
return "XOpenDisplay returned NULL";
const char* error = glxHandleDisplay(instance, data);
data->ffXCloseDisplay(data->display);
return error;
}
static const char* glxPrint(FFinstance* instance)
{
GLXData data;
FF_LIBRARY_LOAD(glx, instance->config.libGLX, "dlopen glx failed", "libGLX.so", 1);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXGetProcAddress, glXGetProcAddress, "dlsym glXGetProcAddress failed");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXOpenDisplay, XOpenDisplay, "dlsym XOpenDisplay returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXChooseVisual, glXChooseVisual, "dlsym glXChooseVisual returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXCreatePixmap, XCreatePixmap, "dlsym XCreatePixmap returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXCreateGLXPixmap, glXCreateGLXPixmap, "dlsym glXCreateGLXPixmap returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXCreateContext, glXCreateContext, "dlsym glXCreateContext returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXMakeCurrent, glXMakeCurrent, "dlsym glXMakeCurrent returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXDestroyContext, glXDestroyContext, "dlsym glXDestroyContext returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXDestroyGLXPixmap, glXDestroyGLXPixmap, "dlsym glXDestroyGLXPixmap returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXFreePixmap, XFreePixmap, "dlsym XFreePixmap returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXCloseDisplay, XCloseDisplay, "dlsym XCloseDisplay returned NULL");
const char* error = glxHandleData(instance, &data);
dlclose(glx);
return error;
}
#endif //FF_HAVE_GLX
#ifdef FF_HAVE_OSMESA
#include <GL/osmesa.h>
typedef struct OSMesaData
{
GLData glData;
FF_LIBRARY_SYMBOL(OSMesaGetProcAddress);
FF_LIBRARY_SYMBOL(OSMesaCreateContext);
FF_LIBRARY_SYMBOL(OSMesaMakeCurrent);
FF_LIBRARY_SYMBOL(OSMesaDestroyContext);
OSMesaContext context;
} OSMesaData;
static const char* osMesaHandleContext(FFinstance* instance, OSMesaData* data)
{
unsigned char buffer[FF_OPENGL_BUFFER_WIDTH * FF_OPENGL_BUFFER_HEIGHT * sizeof(uint32_t)]; // 4 bytes per pixel (RGBA)
if(data->ffOSMesaMakeCurrent(data->context, buffer, GL_UNSIGNED_BYTE, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT) != GL_TRUE)
return "OSMesaMakeCurrent returned GL_FALSE";
return glHandlePrint(instance, &data->glData);
}
static const char* osMesaHandleData(FFinstance* instance, OSMesaData* data)
{
//The case to void* is required here, because OSMESAproc can't be cast to (__typeof__(data->glData.ffglGetString)) without a warning, even though it is the actual type.
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) (void*) data->ffOSMesaGetProcAddress("glGetString");
if(data->glData.ffglGetString == NULL)
return "OSMesaGetProcAddress(glGetString) returned NULL";
data->context = data->ffOSMesaCreateContext(OSMESA_RGBA, NULL);
if(data->context == NULL)
return "OSMesaCreateContext returned NULL";
const char* error = osMesaHandleContext(instance, data);
data->ffOSMesaDestroyContext(data->context);
return error;
}
static const char* osMesaPrint(FFinstance* instance)
{
OSMesaData data;
FF_LIBRARY_LOAD(osmesa, instance->config.libOSMesa, "dlopen osmesa failed", "libOSMesa.so", 8);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaGetProcAddress, OSMesaGetProcAddress, "dlsym OSMesaGetProcAddress returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaCreateContext, OSMesaCreateContext, "dlsym OSMesaCreateContext returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaMakeCurrent, OSMesaMakeCurrent, "dlsym OSMesaMakeCurrent returned NULL");
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaDestroyContext, OSMesaDestroyContext, "dlsym OSMesaDestroyContext returned NULL");
const char* error = osMesaHandleData(instance, &data);
dlclose(osmesa);
return error;
}
#endif //FF_HAVE_OSMESA
static const char* glPrint(FFinstance* instance)
{
if(instance->config.glType == FF_GL_TYPE_GLX)
{
#ifdef FF_HAVE_GLX
return glxPrint(instance);
#else
return "fastfetch was compiled without glx support";
#endif
}
if(instance->config.glType == FF_GL_TYPE_EGL)
{
#ifdef FF_HAVE_EGL
return eglPrint(instance);
#else
return "fastfetch was compiled without egl support";
#endif
}
if(instance->config.glType == FF_GL_TYPE_OSMESA)
{
#ifdef FF_HAVE_OSMESA
return osMesaPrint(instance);
#else
return "fastfetch was compiled without osmesa support";
#endif
}
const char* error = ""; // not NULL dummy value
#ifdef FF_HAVE_EGL
error = eglPrint(instance);
#endif
#ifdef FF_HAVE_GLX
if(error != NULL)
error = glxPrint(instance);
#endif
//We don't use osmesa in auto mode here, because it is a software implementation,
//that doesn't reflect the opengl supported by the hardware
return error;
}
#endif // FF_HAVE_GL
void ffPrintOpenGL(FFinstance* instance)
{
const char* error;
#ifndef FF_HAVE_GL
error = "Fastfetch was built without gl support.";
#else
error = glPrint(instance);
#endif
if(error != NULL)
ffPrintError(instance, FF_OPENGL_MODULE_NAME, 0, &instance->config.openGL, error);
}
+23 -18
View File
@@ -5,14 +5,11 @@
void ffPrintOS(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_OS_MODULE_NAME, &instance->config.osKey, &instance->config.osFormat, FF_OS_NUM_FORMAT_ARGS))
return;
const FFOSResult* result = ffDetectOS(instance);
if(result->name.length == 0 && result->prettyName.length == 0)
{
ffPrintError(instance, FF_OS_MODULE_NAME, 0, &instance->config.osKey, &instance->config.osFormat, FF_OS_NUM_FORMAT_ARGS, "Could not detect OS");
ffPrintError(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, "Could not detect OS");
return;
}
@@ -69,20 +66,28 @@ void ffPrintOS(FFinstance* instance)
ffStrbufAppendC(&os, ']');
}
ffPrintAndWriteToCache(instance, FF_OS_MODULE_NAME, &instance->config.osKey, &os, &instance->config.osFormat, FF_OS_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->systemName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->id},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->idLike},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variant},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variantID},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->versionID},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->codename},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->buildID},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->architecture}
});
if(instance->config.os.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_OS_MODULE_NAME, 0, &instance->config.os.key);
ffStrbufPutTo(&os, stdout);
}
else
{
ffPrintFormat(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, FF_OS_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->systemName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->id},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->idLike},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variant},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variantID},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->versionID},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->codename},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->buildID},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->architecture}
});
}
ffStrbufDestroy(&os);
}
+192 -116
View File
@@ -1,48 +1,26 @@
#include "fastfetch.h"
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#define FF_PACKAGES_MODULE_NAME "Packages"
#define FF_PACKAGES_NUM_FORMAT_ARGS 9
#define FF_PACKAGES_NUM_FORMAT_ARGS 11
#ifdef FF_HAVE_RPM
#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmlog.h>
static uint32_t getRpmPackageCount(FFinstance* instance)
typedef struct PackageCounts
{
FF_LIBRARY_LOAD(rpm, instance->config.librpm, 0, "librpm.so", 5)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
uint32_t pacman;
uint32_t dpkg;
uint32_t rpm;
uint32_t emerge;
uint32_t xbps;
uint32_t nixDefault;
uint32_t flatpak;
uint32_t snap;
// Don't print any error messages
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
uint32_t count = 0;
rpmts ts = NULL;
rpmdbMatchIterator mi = NULL;
if (ffrpmReadConfigFiles(NULL, NULL)) goto exit;
if (!(ts = ffrpmtsCreate())) goto exit;
if (!(mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0))) goto exit;
count = (uint32_t) ffrpmdbGetIteratorCount(mi);
exit:
if (mi) ffrpmdbFreeIterator(mi);
if (ts) ffrpmtsFree(ts);
dlclose(rpm);
return count;
}
#endif
FFstrbuf pacmanBranch;
} PackageCounts;
static uint32_t getNumElements(const char* dirname, unsigned char type)
{
@@ -126,25 +104,19 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDirPath, const char* filename)
return sum;
}
static uint32_t countFilesIn(const char* dirname, const char* filename)
static uint32_t getNixPackages(char* path)
{
FFstrbuf baseDirPath;
ffStrbufInitA(&baseDirPath, 128);
ffStrbufAppendS(&baseDirPath, dirname);
uint32_t result = countFilesRecursive(&baseDirPath, filename);
ffStrbufDestroy(&baseDirPath);
return result;
}
//Nix detection is kinda slow, so we only do it if the dir exists
if(!ffFileExists(path, S_IFDIR))
return 0;
static uint32_t getNixPackages(const FFstrbuf* path)
{
FFstrbuf output;
ffStrbufInitA(&output, 128);
ffProcessAppendStdOut(&output, (char* const[]) {
"nix-store",
"-qR",
path->chars,
path,
NULL
});
@@ -157,89 +129,191 @@ static uint32_t getNixPackages(const FFstrbuf* path)
return result;
}
static uint32_t getNixPackagesDefault()
#ifdef FF_HAVE_RPM
#include <dlfcn.h>
#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmlog.h>
static uint32_t getRpmFromLibrpm(const FFinstance* instance)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffStrbufAppendS(&path, FASTFETCH_TARGET_DIR_ROOT"/nix/var/nix/profiles/default");
uint32_t result = getNixPackages(&path);
ffStrbufDestroy(&path);
return result;
FF_LIBRARY_LOAD(rpm, instance->config.librpm, 0, "librpm.so", 12)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
// Don't print any error messages
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
if(ffrpmReadConfigFiles(NULL, NULL) != 0)
{
dlclose(rpm);
return 0;
}
rpmts ts = ffrpmtsCreate();
if(ts == NULL)
{
dlclose(rpm);
return 0;
}
rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0);
if(mi == NULL)
{
ffrpmtsFree(ts);
dlclose(rpm);
return 0;
}
int count = ffrpmdbGetIteratorCount(mi);
ffrpmdbFreeIterator(mi);
ffrpmtsFree(ts);
dlclose(rpm);
return count > 0 ? (uint32_t) count : 0;
}
#endif
static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
{
uint32_t baseDirLength = baseDir->length;
//pacman
ffStrbufAppendS(baseDir, "/var/lib/pacman/local");
packageCounts->pacman += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//dpkg
ffStrbufAppendS(baseDir, "/var/lib/dpkg/status");
packageCounts->dpkg += getNumStrings(baseDir->chars, "Status: ");
ffStrbufSubstrBefore(baseDir, baseDirLength);
//rpm
ffStrbufAppendS(baseDir, "/var/lib/rpm/rmpdb.sqlite");
packageCounts->rpm += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(blob) FROM Packages");
ffStrbufSubstrBefore(baseDir, baseDirLength);
//emerge
ffStrbufAppendS(baseDir, "/var/db/pkg");
packageCounts->emerge += countFilesRecursive(baseDir, "SIZE");
ffStrbufSubstrBefore(baseDir, baseDirLength);
//xps
ffStrbufAppendS(baseDir, "/var/db/xbps");
packageCounts->xbps += getNumElements(baseDir->chars, DT_REG);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//flatpak
ffStrbufAppendS(baseDir, "/var/lib/flatpak/app");
packageCounts->flatpak += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//nix default
ffStrbufAppendS(baseDir, "/var/nix/profiles/default");
packageCounts->nixDefault += getNixPackages(baseDir->chars);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//snap
ffStrbufAppendS(baseDir, "/snap");
uint32_t snap = getNumElements(baseDir->chars, DT_DIR);
if(snap > 0)
packageCounts->snap += (snap - 1); //Accounting for the /snap/bin folder
ffStrbufSubstrBefore(baseDir, baseDirLength);
//pacman branch
ffStrbufAppendS(baseDir, "/etc/pacman-mirrors.conf");
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
static uint32_t getNixPackagesUser(const FFinstance* instance)
static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffStrbufAppendS(&path, instance->state.passwd->pw_dir);
ffStrbufAppendS(&path, "/.nix-profile");
uint32_t result = getNixPackages(&path);
ffStrbufDestroy(&path);
return result;
ffStrbufAppendS(baseDir, "/bedrock/strata");
DIR* dir = opendir(baseDir->chars);
if(dir == NULL)
return;
ffStrbufAppendC(baseDir, '/');
uint32_t baseDirLength = baseDir->length;
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_type != DT_DIR)
continue;
ffStrbufAppendS(baseDir, entry->d_name);
getPackageCounts(instance, baseDir, packageCounts);
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
closedir(dir);
}
void ffPrintPackages(FFinstance* instance)
{
uint32_t pacman = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/lib/pacman/local", DT_DIR);
uint32_t dpkg = getNumStrings(FASTFETCH_TARGET_DIR_ROOT"/var/lib/dpkg/status", "Status: ");
PackageCounts counts = {0};
ffStrbufInit(&counts.pacmanBranch);
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 512);
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
if(ffStrbufIgnCaseCompS(&ffDetectOS(instance)->id, "bedrock") == 0)
getPackageCountsBedrock(instance, &baseDir, &counts);
else
getPackageCounts(instance, &baseDir, &counts);
// If SQL failed, we can still try with librpm.
// This is needed on openSUSE, which seems to use a proprietary database file
// This method doesn't work on bedrock, so we do it here.
#ifdef FF_HAVE_RPM
uint32_t rpm = getRpmPackageCount(instance);
#else
uint32_t rpm = 0;
if(counts.rpm == 0)
counts.rpm = getRpmFromLibrpm(instance);
#endif
uint32_t emerge = countFilesIn(FASTFETCH_TARGET_DIR_ROOT"/var/db/pkg", "SIZE");
uint32_t xbps = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/db/xbps", DT_REG);
//nix user
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
ffStrbufAppendS(&baseDir, "/.nix-profile");
uint32_t nixUser = getNixPackages(baseDir.chars);
uint32_t nixUser = 0;
uint32_t nixDefault = 0;
//Nix detection is kinda slow, so we only do it if the nix dir exists
if(ffFileExists(FASTFETCH_TARGET_DIR_ROOT"/nix", S_IFDIR))
{
nixUser = getNixPackagesUser(instance);
nixDefault = getNixPackagesDefault();
}
uint32_t flatpak = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/lib/flatpak/app", DT_DIR);
uint32_t snap = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/snap", DT_DIR);
//Accounting for the /snap/bin folder
if(snap > 0)
--snap;
uint32_t all = pacman + dpkg + rpm + emerge + xbps + nixUser + nixDefault + flatpak + snap;
ffStrbufDestroy(&baseDir);
uint32_t all = counts.dpkg + counts.emerge + counts.flatpak + counts.nixDefault + nixUser + counts.pacman + counts.rpm + counts.snap + counts.xbps;
if(all == 0)
{
ffPrintError(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packagesKey, &instance->config.packagesFormat, FF_PACKAGES_NUM_FORMAT_ARGS, "No packages from known package managers found");
ffPrintError(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packages, "No packages from known package managers found");
return;
}
FFstrbuf manjaroBranch;
ffStrbufInit(&manjaroBranch);
if(ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/pacman-mirrors.conf", "Branch =", &manjaroBranch) && manjaroBranch.length == 0)
ffStrbufSetS(&manjaroBranch, "stable");
if(instance->config.packagesFormat.length == 0)
if(instance->config.packages.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packagesKey);
ffPrintLogoAndKey(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packages.key);
#define FF_PRINT_PACKAGE(name) \
if(name > 0) \
if(counts.name > 0) \
{ \
printf("%u ("#name")", name); \
if((all = all - name) > 0) \
printf("%u ("#name")", counts.name); \
if((all = all - counts.name) > 0) \
printf(", "); \
};
if(pacman > 0)
if(counts.pacman > 0)
{
printf("%u (pacman)", pacman);
if(manjaroBranch.length > 0)
printf("[%s]", manjaroBranch.chars);
if((all = all - pacman) > 0)
printf("%u (pacman)", counts.pacman);
if(counts.pacmanBranch.length > 0)
printf("[%s]", counts.pacmanBranch.chars);
if((all = all - counts.pacman) > 0)
printf(", ");
};
@@ -254,10 +328,10 @@ void ffPrintPackages(FFinstance* instance)
printf(", ");
}
if(nixDefault > 0)
if(counts.nixDefault > 0)
{
printf("%u (nix-default)", nixDefault);
if((all = all - nixDefault) > 0)
printf("%u (nix-default)", counts.nixDefault);
if((all = all - counts.nixDefault) > 0)
printf(", ");
}
@@ -273,18 +347,20 @@ void ffPrintPackages(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packagesKey, &instance->config.packagesFormat, NULL, FF_PACKAGES_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packages, FF_PACKAGES_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &all},
{FF_FORMAT_ARG_TYPE_UINT, &pacman},
{FF_FORMAT_ARG_TYPE_STRBUF, &manjaroBranch},
{FF_FORMAT_ARG_TYPE_UINT, &dpkg},
{FF_FORMAT_ARG_TYPE_UINT, &rpm},
{FF_FORMAT_ARG_TYPE_UINT, &emerge},
{FF_FORMAT_ARG_TYPE_UINT, &xbps},
{FF_FORMAT_ARG_TYPE_UINT, &flatpak},
{FF_FORMAT_ARG_TYPE_UINT, &snap}
{FF_FORMAT_ARG_TYPE_UINT, &counts.pacman},
{FF_FORMAT_ARG_TYPE_STRBUF, &counts.pacmanBranch},
{FF_FORMAT_ARG_TYPE_UINT, &counts.dpkg},
{FF_FORMAT_ARG_TYPE_UINT, &counts.rpm},
{FF_FORMAT_ARG_TYPE_UINT, &counts.emerge},
{FF_FORMAT_ARG_TYPE_UINT, &counts.xbps},
{FF_FORMAT_ARG_TYPE_UINT, &nixUser},
{FF_FORMAT_ARG_TYPE_UINT, &counts.nixDefault},
{FF_FORMAT_ARG_TYPE_UINT, &counts.flatpak},
{FF_FORMAT_ARG_TYPE_UINT, &counts.snap}
});
}
ffStrbufDestroy(&manjaroBranch);
ffStrbufDestroy(&counts.pacmanBranch);
}
+4 -4
View File
@@ -11,7 +11,7 @@ void ffPrintPlayer(FFinstance* instance)
if(media->player.length == 0)
{
ffPrintError(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey, &instance->config.playerFormat, FF_PLAYER_NUM_FORMAT_ARGS, "No media player found");
ffPrintError(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.player, "No media player found");
return;
}
@@ -50,14 +50,14 @@ void ffPrintPlayer(FFinstance* instance)
if(playerPrettyIsCustom)
ffStrbufAppendC(&playerPretty, ')');
if(instance->config.playerFormat.length == 0)
if(instance->config.player.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey);
ffPrintLogoAndKey(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.player.key);
ffStrbufPutTo(&playerPretty, stdout);
}
else
{
ffPrintFormatString(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey, &instance->config.playerFormat, NULL, FF_PLAYER_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.player, FF_PLAYER_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &playerPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->player},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->busNameShort}
+3 -3
View File
@@ -5,15 +5,15 @@
void ffPrintProcesses(FFinstance* instance)
{
if(instance->config.processesFormat.length == 0)
if(instance->config.processes.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processesKey);
ffPrintLogoAndKey(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes.key);
printf("%hu\n", instance->state.sysinfo.procs);
}
else
{
ffPrintFormatString(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processesKey, &instance->config.processesFormat, NULL, FF_PROCESSES_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes, FF_PROCESSES_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT16, &instance->state.sysinfo.procs}
});
}
+4 -4
View File
@@ -12,18 +12,18 @@ void ffPrintPublicIp(FFinstance* instance)
if(result.length == 0)
{
ffPrintError(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIpKey, &instance->config.publicIpFormat, FF_PUBLICIP_NUM_FORMAT_ARGS, "Failed to connect to an IP detection server");
ffPrintError(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIP, "Failed to connect to an IP detection server");
return;
}
if(instance->config.publicIpFormat.length == 0)
if(instance->config.publicIP.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIpKey);
ffPrintLogoAndKey(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIP.key);
ffStrbufPutTo(&result, stdout);
}
else
{
ffPrintFormatString(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIpKey, &instance->config.publicIpFormat, NULL, FF_PUBLICIP_NUM_FORMAT_ARGS, (FFformatarg[]) {
ffPrintFormat(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIP, FF_PUBLICIP_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &result}
});
}
+5 -5
View File
@@ -6,7 +6,7 @@
void ffPrintResolution(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "Resolution detection is not supported on Android");
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolution, "Resolution detection is not supported on Android");
return;
#endif
@@ -17,9 +17,9 @@ void ffPrintResolution(FFinstance* instance)
FFResolutionResult* result = ffListGet(&dsResult->resolutions, i);
uint8_t moduleIndex = dsResult->resolutions.length == 1 ? 0 : (uint8_t) (i + 1);
if(instance->config.resolutionFormat.length == 0)
if(instance->config.resolution.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolutionKey);
ffPrintLogoAndKey(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution.key);
printf("%ix%i", result->width, result->height);
if(result->refreshRate > 0)
@@ -29,7 +29,7 @@ void ffPrintResolution(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolutionKey, &instance->config.resolutionFormat, NULL, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) {
ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_INT, &result->width},
{FF_FORMAT_ARG_TYPE_INT, &result->height},
{FF_FORMAT_ARG_TYPE_INT, &result->refreshRate}
@@ -38,5 +38,5 @@ void ffPrintResolution(FFinstance* instance)
}
if(dsResult->resolutions.length == 0)
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "Couldn't detect resolution");
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolution, "Couldn't detect resolution");
}
+1 -1
View File
@@ -5,7 +5,7 @@ void ffPrintSeparator(FFinstance* instance)
const FFTitleResult* result = ffDetectTitle(instance);
uint32_t titleLength = result->userName.length + 1 + result->hostname.length;
ffPrintLogoLine(instance);
ffLogoPrintLine(instance);
if(instance->config.separatorString.length == 0)
{
+4 -7
View File
@@ -1,8 +1,5 @@
#include "fastfetch.h"
#include <string.h>
#include <ctype.h>
#define FF_SHELL_MODULE_NAME "Shell"
#define FF_SHELL_NUM_FORMAT_ARGS 7
@@ -12,13 +9,13 @@ void ffPrintShell(FFinstance* instance)
if(result->shellProcessName.length == 0)
{
ffPrintError(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shellKey, &instance->config.shellFormat, FF_SHELL_NUM_FORMAT_ARGS, "Couldn't detect shell");
ffPrintError(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shell, "Couldn't detect shell");
return;
}
if(instance->config.shellFormat.length == 0)
if(instance->config.shell.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shellKey);
ffPrintLogoAndKey(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shell.key);
fputs(result->shellExeName, stdout);
if(result->shellVersion.length > 0)
@@ -31,7 +28,7 @@ void ffPrintShell(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shellKey, &instance->config.shellFormat, NULL, FF_SHELL_NUM_FORMAT_ARGS, (FFformatarg[]) {
ffPrintFormat(instance, FF_SHELL_MODULE_NAME, 0, &instance->config.shell, FF_SHELL_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &result->shellProcessName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->shellExe},
{FF_FORMAT_ARG_TYPE_STRING, result->shellExeName},
+4 -4
View File
@@ -46,7 +46,7 @@ void ffPrintSong(FFinstance* instance)
if(media->song.length == 0)
{
ffPrintError(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey, &instance->config.songFormat, FF_SONG_NUM_FORMAT_ARGS, "No song detected");
ffPrintError(instance, FF_SONG_MODULE_NAME, 0, &instance->config.song, "No song detected");
return;
}
@@ -67,7 +67,7 @@ void ffPrintSong(FFinstance* instance)
if(songPretty.length == 0)
ffStrbufAppend(&songPretty, &media->song);
if(instance->config.songFormat.length == 0)
if(instance->config.song.outputFormat.length == 0)
{
//We don't expose artistPretty to the format, as it might be empty (when the think that the artist is already in the song title)
FFstrbuf artistPretty;
@@ -79,7 +79,7 @@ void ffPrintSong(FFinstance* instance)
if(artistInSongTitle(&songPretty, &artistPretty))
ffStrbufClear(&artistPretty);
ffPrintLogoAndKey(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey);
ffPrintLogoAndKey(instance, FF_SONG_MODULE_NAME, 0, &instance->config.song.key);
if(artistPretty.length > 0)
{
@@ -98,7 +98,7 @@ void ffPrintSong(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey, &instance->config.songFormat, NULL, FF_SONG_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_SONG_MODULE_NAME, 0, &instance->config.song, FF_SONG_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &songPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->song},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->artist},
+4 -6
View File
@@ -1,8 +1,6 @@
#include "fastfetch.h"
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#define FF_TERMINAL_MODULE_NAME "Terminal"
#define FF_TERMINAL_NUM_FORMAT_ARGS 3
@@ -13,13 +11,13 @@ void ffPrintTerminal(FFinstance* instance)
if(result->terminalProcessName.length == 0)
{
ffPrintError(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminalKey, &instance->config.terminalFormat, FF_TERMINAL_NUM_FORMAT_ARGS, "Couldn't detect terminal");
ffPrintError(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminal, "Couldn't detect terminal");
return;
}
if(instance->config.terminalFormat.length == 0)
if(instance->config.terminal.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminalKey);
ffPrintLogoAndKey(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminal.key);
if(strncmp(result->terminalExeName, result->terminalProcessName.chars, result->terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
puts(result->terminalExeName);
@@ -28,7 +26,7 @@ void ffPrintTerminal(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminalKey, &instance->config.terminalFormat, NULL, FF_TERMINAL_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminal, FF_TERMINAL_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalProcessName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalExe},
{FF_FORMAT_ARG_TYPE_STRING, result->terminalExeName}
+14 -14
View File
@@ -7,18 +7,18 @@ static void printTerminalFont(FFinstance* instance, const char* raw, FFfont* fon
{
if(font->pretty.length == 0)
{
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Terminal font is an empty value");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Terminal font is an empty value");
return;
}
if(instance->config.termFontFormat.length == 0)
if(instance->config.terminalFont.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey);
ffPrintLogoAndKey(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont.key);
ffStrbufPutTo(&font->pretty, stdout);
}
else
{
ffPrintFormatString(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, NULL, FF_TERMFONT_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, FF_TERMFONT_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, raw},
{FF_FORMAT_ARG_TYPE_STRBUF, &font->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &font->size},
@@ -55,7 +55,7 @@ static void printTerminalFontFromConfigFile(FFinstance* instance, const char* co
ffParsePropFileConfig(instance, configFile, start, &fontName);
if(fontName.length == 0)
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't find terminal font in \"$XDG_CONFIG_HOME/%s\"", configFile);
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find terminal font in \"$XDG_CONFIG_HOME/%s\"", configFile);
else
{
FFfont font;
@@ -72,7 +72,7 @@ static void printTerminalFontFromGSettings(FFinstance* instance, char* profilePa
const char* defaultProfile = ffSettingsGetGSettings(instance, profileList, NULL, "default", FF_VARIANT_TYPE_STRING).strValue;
if(defaultProfile == NULL)
{
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't get \"default\" profile from gsettings");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't get \"default\" profile from gsettings");
return;
}
@@ -88,13 +88,13 @@ static void printTerminalFontFromGSettings(FFinstance* instance, char* profilePa
{
fontName = ffSettingsGetGSettings(instance, profile, path.chars, "font", FF_VARIANT_TYPE_STRING).strValue;
if(fontName == NULL)
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't get terminal font from GSettings (%s::%s::font)", profile, path.chars);
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't get terminal font from GSettings (%s::%s::font)", profile, path.chars);
}
else // system font
{
fontName = getSystemMonospaceFont(instance);
if(fontName == NULL)
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Could't get system monospace font name from GSettings / DConf");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Could't get system monospace font name from GSettings / DConf");
}
ffStrbufDestroy(&path);
@@ -116,7 +116,7 @@ static void printKonsole(FFinstance* instance)
if(profile.length == 0)
{
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't find \"DefaultProfile=%[^\\n]\" in \".config/konsolerc\"");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find \"DefaultProfile=%[^\\n]\" in \".config/konsolerc\"");
ffStrbufDestroy(&profile);
return;
}
@@ -131,7 +131,7 @@ static void printKonsole(FFinstance* instance)
ffParsePropFileHome(instance, profilePath.chars, "Font =", &fontName);
if(fontName.length == 0)
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath.chars);
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath.chars);
else
{
FFfont font;
@@ -152,7 +152,7 @@ static void printXCFETerminal(FFinstance* instance)
if(!ffParsePropFileConfig(instance, "xfce4/terminal/terminalrc", "FontUseSystem =", &useSysFont))
{
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't open \"$XDG_CONFIG_HOME/xfce4/terminal/terminalrc\"");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't open \"$XDG_CONFIG_HOME/xfce4/terminal/terminalrc\"");
ffStrbufDestroy(&useSysFont);
return;
}
@@ -169,7 +169,7 @@ static void printXCFETerminal(FFinstance* instance)
const char* fontName = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/MonospaceFontName", FF_VARIANT_TYPE_STRING).strValue;
if(fontName == NULL)
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Couldn't find \"xsettings::/Gtk/MonospaceFontName\" in XFConf");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find \"xsettings::/Gtk/MonospaceFontName\" in XFConf");
else
{
FFfont font;
@@ -211,7 +211,7 @@ void ffPrintTerminalFont(FFinstance* instance)
if(result->terminalProcessName.length == 0)
{
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Terminal font needs successfull terminal detection");
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Terminal font needs successfull terminal detection");
return;
}
@@ -228,5 +228,5 @@ void ffPrintTerminalFont(FFinstance* instance)
else if(ffStrbufStartsWithIgnCaseS(&result->terminalExe, "/dev/tty"))
printTTY(instance);
else
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.termFontKey, &instance->config.termFontFormat, FF_TERMFONT_NUM_FORMAT_ARGS, "Unknown terminal: %s", result->terminalProcessName.chars);
ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Unknown terminal: %s", result->terminalProcessName.chars);
}
+6 -6
View File
@@ -6,7 +6,7 @@
void ffPrintTheme(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.themeKey, &instance->config.themeFormat, FF_THEME_NUM_FORMAT_ARGS, "Theme detection is not supported on Android");
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, "Theme detection is not supported on Android");
return;
#endif
@@ -14,7 +14,7 @@ void ffPrintTheme(FFinstance* instance)
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
{
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.fontKey, &instance->config.fontFormat, FF_THEME_NUM_FORMAT_ARGS, "Theme isn't supported in TTY");
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, "Theme isn't supported in TTY");
return;
}
@@ -25,7 +25,7 @@ void ffPrintTheme(FFinstance* instance)
if(plasma->widgetStyle.length == 0 && plasma->colorScheme.length == 0 && gtk2->length == 0 && gtk3->length == 0 && gtk4->length == 0)
{
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.themeKey, &instance->config.themeFormat, FF_THEME_NUM_FORMAT_ARGS, "No themes found");
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, "No themes found");
return;
}
@@ -40,9 +40,9 @@ void ffPrintTheme(FFinstance* instance)
FF_STRBUF_CREATE(gtkPretty);
ffParseGTK(&gtkPretty, gtk2, gtk3, gtk4);
if(instance->config.themeFormat.length == 0)
if(instance->config.theme.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_THEME_MODULE_NAME, 0, &instance->config.themeKey);
ffPrintLogoAndKey(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme.key);
if(plasma->widgetStyle.length > 0)
{
@@ -80,7 +80,7 @@ void ffPrintTheme(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_THEME_MODULE_NAME, 0, &instance->config.themeKey, &instance->config.themeFormat, NULL, FF_THEME_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, FF_THEME_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma->widgetStyle},
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma->colorScheme},
{FF_FORMAT_ARG_TYPE_STRBUF, &plasmaColorPretty},
+3 -3
View File
@@ -4,14 +4,14 @@
void ffPrintTime(FFinstance* instance)
{
if(instance->config.timeFormat.length > 0)
if(instance->config.time.outputFormat.length > 0)
{
ffPrintDateTimeFormat(instance, FF_TIME_MODULE_NAME, &instance->config.timeKey, &instance->config.timeFormat);
ffPrintDateTimeFormat(instance, FF_TIME_MODULE_NAME, &instance->config.time);
return;
}
const FFDateTimeResult* datetime = ffDetectDateTime(instance);
ffPrintLogoAndKey(instance, FF_TIME_MODULE_NAME, 0, &instance->config.timeKey);
ffPrintLogoAndKey(instance, FF_TIME_MODULE_NAME, 0, &instance->config.time.key);
//hh:mm:ss
printf("%s:%s:%s\n", datetime->hourPretty.chars, datetime->minutePretty.chars, datetime->secondPretty.chars);
+10 -4
View File
@@ -30,17 +30,23 @@ const FFTitleResult* ffDetectTitle(FFinstance* instance)
static inline void printTitlePart(FFinstance* instance, const FFstrbuf* content)
{
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
ffPrintColor(&instance->config.mainColor);
if(!instance->config.pipe)
{
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
ffPrintColor(&instance->config.mainColor);
}
ffStrbufWriteTo(content, stdout);
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(!instance->config.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
}
void ffPrintTitle(FFinstance* instance)
{
const FFTitleResult* result = ffDetectTitle(instance);
ffPrintLogoLine(instance);
ffLogoPrintLine(instance);
printTitlePart(instance, &result->userName);
putchar('@');
+37 -11
View File
@@ -10,28 +10,54 @@ void ffPrintUptime(FFinstance* instance)
uint32_t minutes = (uint32_t) (instance->state.sysinfo.uptime - (days * 86400) - (hours * 3600)) / 60;
uint32_t seconds = (uint32_t) instance->state.sysinfo.uptime - (days * 86400) - (hours * 3600) - (minutes * 60);
if(instance->config.uptimeFormat.length == 0)
if(instance->config.uptime.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_UPTIME_MODULE_NAME, 0, &instance->config.uptimeKey);
ffPrintLogoAndKey(instance, FF_UPTIME_MODULE_NAME, 0, &instance->config.uptime.key);
if(days == 0 && hours == 0 && minutes == 0)
{
printf("%u seconds\n", seconds);
return;
}
else
if(days > 0)
{
if(days > 0)
printf("%u day%s%s, ", days, days <= 1 ? "" : "s", days < 100 ? "" : "(!)");
if(hours > 0)
printf("%u hour%s, ", hours, hours <= 1 ? "" : "s");
if(minutes > 0)
printf("%u min%s", minutes, minutes <= 1 ? "" : "s");
putchar('\n');
printf("%u day", days);
if(days > 1)
putchar('s');
if(days >= 100)
fputs("(!)", stdout);
if(hours > 0 || minutes > 0)
fputs(", ", stdout);
}
if(hours > 0)
{
printf("%u hour", hours);
if(hours > 1)
putchar('s');
if(minutes > 0)
fputs(", ", stdout);
}
if(minutes > 0)
{
printf("%u min", minutes);
if(minutes > 1)
putchar('s');
}
putchar('\n');
}
else
{
ffPrintFormatString(instance, FF_UPTIME_MODULE_NAME, 0, &instance->config.uptimeKey, &instance->config.uptimeFormat, NULL, FF_UPTIME_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_UPTIME_MODULE_NAME, 0, &instance->config.uptime, FF_UPTIME_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &days},
{FF_FORMAT_ARG_TYPE_UINT, &hours},
{FF_FORMAT_ARG_TYPE_UINT, &minutes},
+41
View File
@@ -0,0 +1,41 @@
#include "fastfetch.h"
#define FF_VULKAN_MODULE_NAME "Vulkan"
#define FF_VULKAN_NUM_FORMAT_ARGS 3
void ffPrintVulkan(FFinstance* instance)
{
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
if(vulkan->apiVersion.length == 0 && vulkan->driver.length == 0)
{
ffPrintError(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkan, "Failed to detect vulkan");
return;
}
if(instance->config.vulkan.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkan.key);
if(vulkan->driver.length > 0)
{
printf("%s (driver)", vulkan->driver.chars);
if(vulkan->apiVersion.length > 0)
fputs(", ", stdout);
}
if(vulkan->apiVersion.length > 0)
printf("%s (api version)", vulkan->apiVersion.chars);
putchar('\n');
}
else
{
ffPrintFormat(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkan, FF_VULKAN_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->driver},
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->apiVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->conformanceVersion}
});
}
}
+5 -5
View File
@@ -6,7 +6,7 @@
void ffPrintWM(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_WM_MODULE_NAME, 0, &instance->config.wmKey, &instance->config.wmFormat, FF_WM_NUM_FORMAT_ARGS, "WM detection is not supported on Android");
ffPrintError(instance, FF_WM_MODULE_NAME, 0, &instance->config.wm, "WM detection is not supported on Android");
return;
#endif
@@ -14,13 +14,13 @@ void ffPrintWM(FFinstance* instance)
if(result->wmPrettyName.length == 0)
{
ffPrintError(instance, FF_WM_MODULE_NAME, 0, &instance->config.wmKey, &instance->config.wmFormat, FF_WM_NUM_FORMAT_ARGS, "No WM found");
ffPrintError(instance, FF_WM_MODULE_NAME, 0, &instance->config.wm, "No WM found");
return;
}
if(instance->config.wmFormat.length == 0)
if(instance->config.wm.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_WM_MODULE_NAME, 0, &instance->config.wmKey);
ffPrintLogoAndKey(instance, FF_WM_MODULE_NAME, 0, &instance->config.wm.key);
ffStrbufWriteTo(&result->wmPrettyName, stdout);
@@ -35,7 +35,7 @@ void ffPrintWM(FFinstance* instance)
}
else
{
ffPrintFormatString(instance, FF_WM_MODULE_NAME, 0, &instance->config.wmKey, &instance->config.wmFormat, NULL, FF_WM_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_WM_MODULE_NAME, 0, &instance->config.wm, FF_WM_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->wmProcessName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->wmPrettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->wmProtocolName}
+16 -14
View File
@@ -1,4 +1,6 @@
#include "fastfetch.h"
#include <stdlib.h>
#include <string.h>
#define FF_WMTHEME_MODULE_NAME "WM Theme"
@@ -6,14 +8,14 @@
static void printWMTheme(FFinstance* instance, const char* theme)
{
if(instance->config.wmThemeFormat.length == 0)
if(instance->config.wmTheme.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey);
ffPrintLogoAndKey(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme.key);
puts(theme);
}
else
{
ffPrintFormatString(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, NULL, FF_WMTHEME_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormat(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, FF_WMTHEME_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, theme}
});
}
@@ -26,7 +28,7 @@ static void printWMThemeFromConfigFile(FFinstance* instance, const char* configF
if(!ffParsePropFileConfig(instance, configFile, themeRegex, &theme))
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Config file %s doesn't exist", configFile);
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Config file %s doesn't exist", configFile);
ffStrbufDestroy(&theme);
return;
}
@@ -37,7 +39,7 @@ static void printWMThemeFromConfigFile(FFinstance* instance, const char* configF
if(defaultValue == NULL)
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't find WM theme in %s", configFile);
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't find WM theme in %s", configFile);
return;
}
@@ -66,7 +68,7 @@ static void printWMThemeFromSettings(FFinstance* instance, const char* dconfKey,
if(!ffStrSet(theme))
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't find WM theme in DConf or GSettings");
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't find WM theme in DConf or GSettings");
return;
}
@@ -99,7 +101,7 @@ static void printGTKThemeAsWMTheme(FFinstance* instance)
return;
}
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't detect GTK4/3/2 theme");
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't detect GTK4/3/2 theme");
}
static void printMutter(FFinstance* instance)
@@ -121,7 +123,7 @@ static void printMuffin(FFinstance* instance)
if(name == NULL && theme == NULL)
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't find muffin theme in GSettings / DConf");
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't find muffin theme in GSettings / DConf");
return;
}
@@ -150,7 +152,7 @@ static void printXFWM4(FFinstance* instance)
if(theme == NULL)
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't find xfwm4::/general/theme in XFConf");
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't find xfwm4::/general/theme in XFConf");
return;
}
@@ -177,7 +179,7 @@ static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName)
FILE* file = fopen(absolutePath.chars, "r");
if(file == NULL)
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't open \"%s\"", absolutePath.chars);
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't open \"%s\"", absolutePath.chars);
ffStrbufDestroy(&absolutePath);
return;
@@ -213,7 +215,7 @@ static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName)
fclose(file);
if(theme.length == 0)
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't find theme name in \"%s\"", absolutePath.chars);
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Couldn't find theme name in \"%s\"", absolutePath.chars);
else
printWMTheme(instance, theme.chars);
@@ -224,7 +226,7 @@ static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName)
void ffPrintWMTheme(FFinstance* instance)
{
#ifdef __ANDROID__
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "WM theme detection is not supported on Android");
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "WM theme detection is not supported on Android");
return;
#endif
@@ -232,7 +234,7 @@ void ffPrintWMTheme(FFinstance* instance)
if(result->wmPrettyName.length == 0)
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "WM Theme needs sucessfull WM detection");
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "WM Theme needs sucessfull WM detection");
return;
}
@@ -254,5 +256,5 @@ void ffPrintWMTheme(FFinstance* instance)
else if(ffStrbufIgnCaseCompS(&result->wmPrettyName, "Openbox") == 0)
printOpenbox(instance, &result->dePrettyName);
else
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Unknown WM: %s", result->wmPrettyName.chars);
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Unknown WM: %s", result->wmPrettyName.chars);
}
+1 -2
View File
@@ -1,7 +1,6 @@
#include "FFlist.h"
#include <malloc.h>
#include <memory.h>
#include <stdlib.h>
void ffListInit(FFlist* list, uint32_t elementSize)
{
+20 -31
View File
@@ -1,9 +1,8 @@
#include "FFstrbuf.h"
#include <malloc.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
static char* CHAR_NULL_PTR = "";
@@ -29,31 +28,12 @@ void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src)
ffStrbufAppend(strbuf, src);
}
static void setCapacity(FFstrbuf* strbuf, uint32_t capacity)
uint32_t ffStrbufGetFree(const FFstrbuf* strbuf)
{
if(strbuf->allocated == 0)
{
strbuf->chars = malloc(sizeof(*strbuf->chars) * capacity);
strbuf->chars[0] = '\0';
}
else
strbuf->chars = realloc(strbuf->chars, sizeof(*strbuf->chars) * capacity);
return 0;
strbuf->allocated = capacity;
}
void ffStrbufEnsureCapacity(FFstrbuf* strbuf, uint32_t capacity)
{
if(strbuf->allocated > capacity || capacity == 0)
return;
if(capacity == UINT32_MAX)
{
fputs("Warning: ffStrbufEnsureCapacity called with UINT32_MAX. Highest allowed value is UINT32_MAX - 1. Exiting.\n", stderr);
exit(812);
}
setCapacity(strbuf, capacity + 1); // + 1 for the null byte
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
}
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free)
@@ -68,15 +48,15 @@ void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free)
while((strbuf->length + free + 1) > allocate) // + 1 for the null byte
allocate *= 2;
setCapacity(strbuf, allocate);
}
uint32_t ffStrbufGetFree(const FFstrbuf* strbuf)
{
if(strbuf->allocated == 0)
return 0;
{
strbuf->chars = malloc(sizeof(*strbuf->chars) * allocate);
strbuf->chars[0] = '\0';
}
else
strbuf->chars = realloc(strbuf->chars, sizeof(*strbuf->chars) * allocate);
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
strbuf->allocated = allocate;
}
void ffStrbufClear(FFstrbuf* strbuf)
@@ -545,6 +525,15 @@ void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file)
fputc('\n', file);
}
double ffStrbufToDouble(const FFstrbuf* strbuf)
{
double value;
if(sscanf(strbuf->chars, "%lf", &value) != 1)
return 0.0 / 0.0; //NaN
return value;
}
void ffStrbufDestroy(FFstrbuf* strbuf)
{
free(strbuf->chars);
+2 -1
View File
@@ -23,7 +23,6 @@ void ffStrbufInit(FFstrbuf* strbuf);
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src);
void ffStrbufEnsureCapacity(FFstrbuf* strbuf, uint32_t capacity);
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);
uint32_t ffStrbufGetFree(const FFstrbuf* strbuf);
@@ -94,6 +93,8 @@ bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end);
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file);
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file);
double ffStrbufToDouble(const FFstrbuf* strbuf);
void ffStrbufDestroy(FFstrbuf* strbuf);
#endif
+3 -4
View File
@@ -1,9 +1,8 @@
#include <stdint.h>
#include <malloc.h>
#include <string.h>
#include "FFvaluestore.h"
#include <string.h>
#include <stdlib.h>
void ffValuestoreInit(FFvaluestore* vs)
{
vs->capacity = 32;
+1
View File
@@ -4,6 +4,7 @@
#define FASTFETCH_INCLUDED_FFVALUESTORE
#include <stdbool.h>
#include <stdint.h>
typedef struct FFvaluestorePair
{
-82
View File
@@ -1,82 +0,0 @@
#include "fastfetch.h"
#include <time.h>
#define FASTFETCH_TEST_PERFORMANCE(func) \
{ \
struct timespec start, end; \
clock_gettime(CLOCK_REALTIME, &start); \
func; \
clock_gettime(CLOCK_REALTIME, &end); \
long nanos = end.tv_nsec - start.tv_nsec; \
printf("\033[F"); \
for(uint8_t i = 0; i < 125; i++) printf("\033[C"); \
printf("%08ldns\n", nanos); \
} \
int main(int argc, char** argv)
{
FF_UNUSED(argc, argv);
FFinstance instance;
FASTFETCH_TEST_PERFORMANCE(
puts("Initialization");
ffInitInstance(&instance);
)
instance.config.showErrors = true;
instance.config.recache = argc == 1;
instance.config.cacheSave = false;
ffStrbufSetS(&instance.config.songFormat, "{}"); //Otherwise the line is too long
FASTFETCH_TEST_PERFORMANCE(
puts("Thread starting");
ffStartDetectionThreads(&instance);
)
FASTFETCH_TEST_PERFORMANCE(
puts("Starting");
ffStart(&instance);
)
FASTFETCH_TEST_PERFORMANCE(ffPrintTitle(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintSeparator(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintOS(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintHost(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintKernel(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintUptime(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintProcesses(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintPackages(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintShell(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintResolution(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintDesktopEnvironment(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintWM(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintWMTheme(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintTheme(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintIcons(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintFont(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintTerminal(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintTerminalFont(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintCPU(&instance))
//FASTFETCH_TEST_PERFORMANCE(ffPrintCPUUsage(&instance)) // Doesn't make sense, contains a sleep call
FASTFETCH_TEST_PERFORMANCE(ffPrintGPU(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintMemory(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintDisk(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintBattery(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintPlayer(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintSong(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintLocalIp(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintPublicIp(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintDateTime(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintLocale(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintBreak(&instance))
FASTFETCH_TEST_PERFORMANCE(ffPrintColors(&instance))
FASTFETCH_TEST_PERFORMANCE(
puts("Finishing");
ffFinish(&instance);
)
return 0;
}
-6
View File
@@ -1,6 +0,0 @@
#!/bin/env sh
mkdir -p build/
cd build
cmake ..
cmake --build . --target fastfetch-test-performance -j$(nproc)
./fastfetch-test-performance "$@"