diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 05b0af1714..0b5e198c00 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -94,7 +94,7 @@ jobs: path: ./fastfetch-*.* release: - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch' name: Release runs-on: ubuntu-latest needs: diff --git a/CMakeLists.txt b/CMakeLists.txt index 98f83b3a88..95ecba432e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX" OFF) cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX" OFF) cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX" OFF) cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX" OFF) +cmake_dependent_option(ENABLE_LIBPLIST "Enable libplist" ON "APPLE" OFF) option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds @@ -74,8 +75,11 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion") if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX}) # Used for dlopen finding dylibs installed by homebrew, reversed for future usage # `/opt/homebrew/lib` is not on dlopen search path by default - set(CMAKE_EXE_LINKER_FLAGS "-Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib") endif() +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined") +set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -rdynamic -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined") + include(CheckIPOSupported) check_ipo_supported(RESULT IPO_SUPPORTED) @@ -243,7 +247,9 @@ if(APPLE) src/detection/battery/battery_apple.c src/detection/memory/memory_apple.c src/detection/displayserver/displayserver_apple.c + src/modules/terminalfont_apple.c src/util/apple/cfdict_helpers.c + src/util/apple/osascript.m ) elseif(ANDROID) list(APPEND LIBFASTFETCH_SRC @@ -254,6 +260,7 @@ elseif(ANDROID) src/detection/battery/battery_android.c src/detection/memory/memory_linux.c src/detection/displayserver/displayserver_android.c + src/modules/terminalfont_linux.c ) else() list(APPEND LIBFASTFETCH_SRC @@ -268,6 +275,7 @@ else() src/detection/displayserver/linux/xcb.c src/detection/displayserver/linux/xlib.c src/detection/displayserver/linux/wmde.c + src/modules/terminalfont_linux.c ) endif() @@ -320,6 +328,7 @@ ff_lib_enable(EGL egl) ff_lib_enable(GLX glx) ff_lib_enable(OSMESA osmesa) ff_lib_enable(OPENCL OpenCL) +ff_lib_enable(LIBPLIST libplist-2.0) if(APPLE) target_link_libraries(libfastfetch @@ -328,6 +337,7 @@ if(APPLE) PRIVATE "-framework CoreGraphics" PRIVATE "-framework OpenGL" PRIVATE "-framework OpenCL" + PRIVATE "-framework Cocoa" ) endif() diff --git a/README.md b/README.md index 12940d85c5..8dbec36fed 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ The following libraries are used if present at runtime: * [`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. +* [`libplist`](https://github.com/libimobiledevice/libplist): Binary `plist` file parser. Needed for iTerm2 Terminal font. ## Support status All categories not listed here should work without needing a specific implementation. diff --git a/src/common/font.c b/src/common/font.c index 3915fa18d3..c48f772211 100644 --- a/src/common/font.c +++ b/src/common/font.c @@ -204,6 +204,20 @@ void ffFontInitCopy(FFfont* font, const char* name) ffFontInitValues(font, name, NULL); } +void ffFontInitWithSpace(FFfont* font, const char* rawName) +{ + const char* pspace = strrchr(rawName, ' '); + if(pspace == NULL) + return ffFontInitCopy(font, rawName); + + fontInit(font); + + ffStrbufAppendNS(&font->name, (uint32_t)(pspace - rawName), rawName); + ffStrbufAppendS(&font->size, pspace + 1); + + fontInitPretty(font); +} + void ffFontDestroy(FFfont* font) { ffStrbufDestroy(&font->pretty); diff --git a/src/common/font.h b/src/common/font.h index a9d85b0dc7..605f7c4307 100644 --- a/src/common/font.h +++ b/src/common/font.h @@ -18,6 +18,7 @@ void ffFontInitQt(FFfont* font, const char* data); void ffFontInitPango(FFfont* font, const char* data); void ffFontInitCopy(FFfont* font, const char* name); void ffFontInitValues(FFfont* font, const char* name, const char* size); +void ffFontInitWithSpace(FFfont* font, const char* rawName); void ffFontDestroy(FFfont* font); #endif diff --git a/src/common/init.c b/src/common/init.c index a1564f35b1..08b945eb7e 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -212,6 +212,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.libGLX, 0); ffStrbufInitA(&instance->config.libOSMesa, 0); ffStrbufInitA(&instance->config.libOpenCL, 0); + ffStrbufInitA(&instance->config.libplist, 0); instance->config.titleFQDN = false; diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 23ff7e688b..5050ba6464 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -320,3 +320,4 @@ #--lib-glx /usr/lib/libGLX.so #--lib-osmesa /usr/lib/libOSMesa.so #--lib-opencl /usr/lib/libOpenCL.so +#--lib-plist /usr/local/bin/libplist-2.0.dylib diff --git a/src/data/help.txt b/src/data/help.txt index a9734ee94b..283ca01a06 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -84,6 +84,7 @@ Library options: Set the path of a library to load --lib-glx --lib-osmesa --lib-opencl + --lib-plist Module specific options: --title-fqdn : sets if the title should use fully qualified domain name. Default is false. diff --git a/src/detection/memory/memory_apple.c b/src/detection/memory/memory_apple.c index 3060613131..eb264c78e4 100644 --- a/src/detection/memory/memory_apple.c +++ b/src/detection/memory/memory_apple.c @@ -1,9 +1,9 @@ #include "memory.h" #include "common/settings.h" - #include #include +#include void ffDetectMemoryImpl(FFMemoryResult* memory) { @@ -21,4 +21,11 @@ void ffDetectMemoryImpl(FFMemoryResult* memory) return; memory->ram.bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * pagesize; + + struct xsw_usage swap; + size_t size = sizeof(swap); + if (sysctlbyname("vm.swapusage", &swap, &size, 0, 0) == -1) + return; + memory->swap.bytesTotal = swap.xsu_total; + memory->swap.bytesUsed = swap.xsu_used; } diff --git a/src/fastfetch.c b/src/fastfetch.c index af2e898e95..155237af9b 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1228,6 +1228,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.libOSMesa); else if(strcasecmp(key, "--lib-opencl") == 0) optionParseString(key, value, &instance->config.libOpenCL); + else if(strcasecmp(key, "--lib-plist") == 0) + optionParseString(key, value, &instance->config.libplist); ////////////////// //Module options// diff --git a/src/fastfetch.h b/src/fastfetch.h index d47a689e6a..84187d5767 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -148,6 +148,7 @@ typedef struct FFconfig FFstrbuf libGLX; FFstrbuf libOSMesa; FFstrbuf libOpenCL; + FFstrbuf libplist; bool titleFQDN; diff --git a/src/modules/processes.c b/src/modules/processes.c index 4b3addb94e..bb343c25b9 100644 --- a/src/modules/processes.c +++ b/src/modules/processes.c @@ -4,12 +4,24 @@ #define FF_PROCESSES_MODULE_NAME "Processes" #define FF_PROCESSES_NUM_FORMAT_ARGS 1 +#ifdef __APPLE__ + #include +#endif + void ffPrintProcesses(FFinstance* instance) { #if FF_HAVE_SYSINFO_H uint16_t numProcesses = instance->state.sysinfo.procs; #else - uint16_t numProcesses = 0; + int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + size_t length; + + if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0) + { + ffPrintError(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes, "sysctl() failed"); + return; + } + uint16_t numProcesses = (uint16_t)(length / sizeof(struct kinfo_proc)); #endif if(instance->config.processes.outputFormat.length == 0) diff --git a/src/modules/terminalfont.c b/src/modules/terminalfont.c index b2e8dc1782..c7ccd61093 100644 --- a/src/modules/terminalfont.c +++ b/src/modules/terminalfont.c @@ -2,15 +2,10 @@ #include "common/properties.h" #include "common/printing.h" #include "common/font.h" -#include "common/settings.h" #include "common/processing.h" -#include "detection/displayserver/displayserver.h" -#include "detection/terminalshell.h" +#include "terminalfont.h" -#define FF_TERMFONT_MODULE_NAME "Terminal Font" -#define FF_TERMFONT_NUM_FORMAT_ARGS 5 - -static void printTerminalFont(FFinstance* instance, const char* raw, FFfont* font) +void ffPrintTerminalFontResult(FFinstance* instance, const char* raw, FFfont* font) { if(font->pretty.length == 0) { @@ -35,157 +30,6 @@ static void printTerminalFont(FFinstance* instance, const char* raw, FFfont* fon } } -static const char* getSystemMonospaceFont(FFinstance* instance) -{ - const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0) - { - const char* systemMonospaceFont = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/monospace-font-name", "org.cinnamon.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; - if(systemMonospaceFont != NULL) - return systemMonospaceFont; - } - else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) - { - const char* systemMonospaceFont = ffSettingsGet(instance, "/org/mate/interface/monospace-font-name", "org.mate.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; - if(systemMonospaceFont != NULL) - return systemMonospaceFont; - } - - return ffSettingsGet(instance, "/org/gnome/desktop/interface/monospace-font-name", "org.gnome.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; -} - -static void printTerminalFontFromConfigFile(FFinstance* instance, const char* configFile, const char* start) -{ - FFstrbuf fontName; - ffStrbufInit(&fontName); - ffParsePropFileConfig(instance, configFile, start, &fontName); - - if(fontName.length == 0) - ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find terminal font in \"$XDG_CONFIG_HOME/%s\"", configFile); - else - { - FFfont font; - ffFontInitPango(&font, fontName.chars); - printTerminalFont(instance, fontName.chars, &font); - ffFontDestroy(&font); - } - - ffStrbufDestroy(&fontName); -} - -static void printTerminalFontFromGSettings(FFinstance* instance, char* profilePath, char* profileList, char* profile) -{ - 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.terminalFont, "Couldn't get \"default\" profile from gsettings"); - return; - } - - FFstrbuf path; - ffStrbufInitA(&path, 128); - ffStrbufAppendS(&path, profilePath); - ffStrbufAppendS(&path, defaultProfile); - ffStrbufAppendC(&path, '/'); - - const char* fontName; - - if(!ffSettingsGetGSettings(instance, profile, path.chars, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue) // custom font - { - fontName = ffSettingsGetGSettings(instance, profile, path.chars, "font", FF_VARIANT_TYPE_STRING).strValue; - if(fontName == NULL) - 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.terminalFont, "Could't get system monospace font name from GSettings / DConf"); - } - - ffStrbufDestroy(&path); - - if(fontName == NULL) - return; - - FFfont font; - ffFontInitPango(&font, fontName); - printTerminalFont(instance, fontName, &font); - ffFontDestroy(&font); -} - -static void printKonsole(FFinstance* instance) -{ - FFstrbuf profile; - ffStrbufInit(&profile); - ffParsePropFileConfig(instance, "konsolerc", "DefaultProfile =", &profile); - - if(profile.length == 0) - { - ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "%s", "Couldn't find \"DefaultProfile=%[^\\n]\" in \".config/konsolerc\""); - ffStrbufDestroy(&profile); - return; - } - - FFstrbuf profilePath; - ffStrbufInitA(&profilePath, 64); - ffStrbufAppendS(&profilePath, ".local/share/konsole/"); - ffStrbufAppend(&profilePath, &profile); - - FFstrbuf fontName; - ffStrbufInit(&fontName); - ffParsePropFileHome(instance, profilePath.chars, "Font =", &fontName); - - if(fontName.length == 0) - ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath.chars); - else - { - FFfont font; - ffFontInitQt(&font, fontName.chars); - printTerminalFont(instance, fontName.chars, &font); - ffFontDestroy(&font); - } - - ffStrbufDestroy(&fontName); - ffStrbufDestroy(&profilePath); - ffStrbufDestroy(&profile); -} - -static void printXCFETerminal(FFinstance* instance) -{ - FFstrbuf useSysFont; - ffStrbufInit(&useSysFont); - - if(!ffParsePropFileConfig(instance, "xfce4/terminal/terminalrc", "FontUseSystem =", &useSysFont)) - { - ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't open \"$XDG_CONFIG_HOME/xfce4/terminal/terminalrc\""); - ffStrbufDestroy(&useSysFont); - return; - } - - if(useSysFont.length == 0 || ffStrbufIgnCaseCompS(&useSysFont, "FALSE") == 0) - { - printTerminalFontFromConfigFile(instance, "xfce4/terminal/terminalrc", "FontName ="); - ffStrbufDestroy(&useSysFont); - return; - } - - ffStrbufDestroy(&useSysFont); - - 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.terminalFont, "Couldn't find \"xsettings::/Gtk/MonospaceFontName\" in XFConf"); - else - { - FFfont font; - ffFontInitPango(&font, fontName); - printTerminalFont(instance, fontName, &font); - ffFontDestroy(&font); - } -} - static void printAlacritty(FFinstance* instance) { FFstrbuf fontName; FFstrbuf fontSize; @@ -214,7 +58,7 @@ static void printAlacritty(FFinstance* instance) { FFfont font; ffFontInitValues(&font, fontName.chars, fontSize.chars); - printTerminalFont(instance, fontName.chars, &font); + ffPrintTerminalFontResult(instance, fontName.chars, &font); ffFontDestroy(&font); ffStrbufDestroy(&fontName); @@ -242,7 +86,7 @@ static void printTTY(FFinstance* instance) FFfont font; ffFontInitCopy(&font, fontName.chars); - printTerminalFont(instance, fontName.chars, &font); + ffPrintTerminalFontResult(instance, fontName.chars, &font); ffFontDestroy(&font); ffStrbufDestroy(&fontName); } @@ -257,17 +101,9 @@ void ffPrintTerminalFont(FFinstance* instance) return; } - if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "konsole") == 0) - printKonsole(instance); - else if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "xfce4-terminal") == 0) - printXCFETerminal(instance); - else if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "lxterminal") == 0) - printTerminalFontFromConfigFile(instance, "lxterminal/lxterminal.conf", "fontname ="); - else if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "tilix") == 0) - printTerminalFontFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile"); - else if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "gnome-terminal-") == 0) - printTerminalFontFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile"); - else if(ffStrbufStartsWithIgnCaseS(&result->terminalExe, "/dev/tty")) + if(ffPrintTerminalFontPlatform(instance, result)) + return; + if(ffStrbufStartsWithIgnCaseS(&result->terminalExe, "/dev/tty")) printTTY(instance); else if(ffStrbufIgnCaseCompS(&result->terminalProcessName, "alacritty") == 0) printAlacritty(instance); diff --git a/src/modules/terminalfont.h b/src/modules/terminalfont.h new file mode 100644 index 0000000000..45c6f080c4 --- /dev/null +++ b/src/modules/terminalfont.h @@ -0,0 +1,15 @@ +#pragma once + +#ifndef FF_INCLUDED_modules_terminalfont +#define FF_INCLUDED_modules_terminalfont + +#include "fastfetch.h" +#include "detection/terminalshell.h" + +#define FF_TERMFONT_MODULE_NAME "Terminal Font" +#define FF_TERMFONT_NUM_FORMAT_ARGS 5 + +void ffPrintTerminalFontResult(FFinstance* instance, const char* raw, FFfont* font); +bool ffPrintTerminalFontPlatform(FFinstance* instance, const FFTerminalShellResult* shellInfo); + +#endif diff --git a/src/modules/terminalfont_apple.c b/src/modules/terminalfont_apple.c new file mode 100644 index 0000000000..d7454a302b --- /dev/null +++ b/src/modules/terminalfont_apple.c @@ -0,0 +1,143 @@ +#include "fastfetch.h" +#include "common/printing.h" +#include "common/font.h" +#include "common/io.h" +#include "common/library.h" +#include "util/apple/osascript.h" +#include "terminalfont.h" + +#include +#include + +#ifdef FF_HAVE_LIBPLIST + +#include + +static char* printIterm2Impl(FFinstance* instance, const char* profile, FFstrbuf* content) +{ + FF_LIBRARY_LOAD(libplist, instance->config.libplist, "dlopen libplist failed", "libplist-2.0"FF_LIBRARY_EXTENSION, 2); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_is_binary); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_from_bin); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_from_xml); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_array_new_iter); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_access_path); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_array_next_item); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_string_val_compare); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_dict_get_item); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_get_string_ptr); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_free); + + plist_t root_node = NULL; + if (ffplist_is_binary(content->chars, content->length)) + ffplist_from_bin(content->chars, content->length, &root_node); + else + ffplist_from_xml(content->chars, content->length, &root_node); + + if(root_node == NULL) + return "parsing iTerm preference file failed"; + + plist_t bookmarks = ffplist_access_path(root_node, 1, "New Bookmarks"); + + plist_array_iter iter = NULL; + ffplist_array_new_iter(bookmarks, &iter); + plist_t item = NULL; + do + { + ffplist_array_next_item(bookmarks, iter, &item); + if(ffplist_string_val_compare(ffplist_dict_get_item(item, "Name"), profile) == 0) + break; + } while(item != NULL); + free(iter); + + if(item == NULL) + { + ffplist_free(root_node); + return "find profile bookmark failed"; + } + + item = ffplist_dict_get_item(item, "Normal Font"); + if (item == NULL) + { + ffplist_free(root_node); + return "find Normal Font key failed"; + } + + FFfont font; + ffFontInitWithSpace(&font, ffplist_get_string_ptr(item, NULL)); + ffPrintTerminalFontResult(instance, font.name.chars, &font); + ffFontDestroy(&font); + ffplist_free(root_node); + return NULL; +} + +#endif //FF_HAVE_LIBPLIST + +static void printIterm2(FFinstance* instance) +{ + #ifdef FF_HAVE_LIBPLIST + const char* profile = getenv("ITERM_PROFILE"); + if (profile == NULL) + { + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Unknown iTerm profile"); + return; + } + + FFstrbuf fileName; + ffStrbufInit(&fileName); + ffStrbufAppendS(&fileName, instance->state.passwd->pw_dir); + ffStrbufAppendS(&fileName, "/Library/Preferences/com.googlecode.iterm2.plist"); + + FFstrbuf content; + ffStrbufInit(&content); + bool success = ffAppendFileBuffer(fileName.chars, &content); + ffStrbufDestroy(&fileName); + + if(success) + { + const char* error = printIterm2Impl(instance, profile, &content); + if (error) + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "%s", error); + } + else + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Read iTerm preference file failed"); + + ffStrbufDestroy(&content); + #else + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Parse iTerm preferences requires libplist to be installed"); + #endif +} + +static void printAppleTerminal(FFinstance* instance) +{ + FFstrbuf fontName; + ffStrbufInit(&fontName); + if(!ffOsascript("tell application \"Terminal\" to font name of window frontmost", &fontName)) + { + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "osascript failed"); + return; + } + + FFstrbuf fontSize; + ffStrbufInit(&fontSize); + ffOsascript("tell application \"Terminal\" to font size of window frontmost", &fontSize); + + FFfont font; + ffFontInitValues(&font, fontName.chars, fontSize.chars); + ffPrintTerminalFontResult(instance, fontName.chars, &font); + ffFontDestroy(&font); + + ffStrbufDestroy(&fontName); + ffStrbufDestroy(&fontSize); +} + +bool ffPrintTerminalFontPlatform(FFinstance* instance, const FFTerminalShellResult* shellInfo) +{ + bool success = true; + if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "iterm.app") == 0) + printIterm2(instance); + else if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "Apple_Terminal") == 0) + printAppleTerminal(instance); + else + success = false; + return success; +} diff --git a/src/modules/terminalfont_linux.c b/src/modules/terminalfont_linux.c new file mode 100644 index 0000000000..2665268336 --- /dev/null +++ b/src/modules/terminalfont_linux.c @@ -0,0 +1,177 @@ +#include "fastfetch.h" +#include "common/properties.h" +#include "common/printing.h" +#include "common/font.h" +#include "common/settings.h" +#include "detection/displayserver/displayserver.h" +#include "detection/terminalshell.h" +#include "terminalfont.h" + +static const char* getSystemMonospaceFont(FFinstance* instance) +{ + const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); + + if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0) + { + const char* systemMonospaceFont = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/monospace-font-name", "org.cinnamon.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; + if(systemMonospaceFont != NULL) + return systemMonospaceFont; + } + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) + { + const char* systemMonospaceFont = ffSettingsGet(instance, "/org/mate/interface/monospace-font-name", "org.mate.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; + if(systemMonospaceFont != NULL) + return systemMonospaceFont; + } + + return ffSettingsGet(instance, "/org/gnome/desktop/interface/monospace-font-name", "org.gnome.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; +} + +static void printTerminalFontFromConfigFile(FFinstance* instance, const char* configFile, const char* start) +{ + FFstrbuf fontName; + ffStrbufInit(&fontName); + ffParsePropFileConfig(instance, configFile, start, &fontName); + + if(fontName.length == 0) + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find terminal font in \"$XDG_CONFIG_HOME/%s\"", configFile); + else + { + FFfont font; + ffFontInitPango(&font, fontName.chars); + ffPrintTerminalFontResult(instance, fontName.chars, &font); + ffFontDestroy(&font); + } + + ffStrbufDestroy(&fontName); +} + +static void printTerminalFontFromGSettings(FFinstance* instance, char* profilePath, char* profileList, char* profile) +{ + 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.terminalFont, "Couldn't get \"default\" profile from gsettings"); + return; + } + + FFstrbuf path; + ffStrbufInitA(&path, 128); + ffStrbufAppendS(&path, profilePath); + ffStrbufAppendS(&path, defaultProfile); + ffStrbufAppendC(&path, '/'); + + const char* fontName; + + if(!ffSettingsGetGSettings(instance, profile, path.chars, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue) // custom font + { + fontName = ffSettingsGetGSettings(instance, profile, path.chars, "font", FF_VARIANT_TYPE_STRING).strValue; + if(fontName == NULL) + 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.terminalFont, "Could't get system monospace font name from GSettings / DConf"); + } + + ffStrbufDestroy(&path); + + if(fontName == NULL) + return; + + FFfont font; + ffFontInitPango(&font, fontName); + ffPrintTerminalFontResult(instance, fontName, &font); + ffFontDestroy(&font); +} + +static void printKonsole(FFinstance* instance) +{ + FFstrbuf profile; + ffStrbufInit(&profile); + ffParsePropFileConfig(instance, "konsolerc", "DefaultProfile =", &profile); + + if(profile.length == 0) + { + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "%s", "Couldn't find \"DefaultProfile=%[^\\n]\" in \".config/konsolerc\""); + ffStrbufDestroy(&profile); + return; + } + + FFstrbuf profilePath; + ffStrbufInitA(&profilePath, 64); + ffStrbufAppendS(&profilePath, ".local/share/konsole/"); + ffStrbufAppend(&profilePath, &profile); + + FFstrbuf fontName; + ffStrbufInit(&fontName); + ffParsePropFileHome(instance, profilePath.chars, "Font =", &fontName); + + if(fontName.length == 0) + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath.chars); + else + { + FFfont font; + ffFontInitQt(&font, fontName.chars); + ffPrintTerminalFontResult(instance, fontName.chars, &font); + ffFontDestroy(&font); + } + + ffStrbufDestroy(&fontName); + ffStrbufDestroy(&profilePath); + ffStrbufDestroy(&profile); +} + +static void printXCFETerminal(FFinstance* instance) +{ + FFstrbuf useSysFont; + ffStrbufInit(&useSysFont); + + if(!ffParsePropFileConfig(instance, "xfce4/terminal/terminalrc", "FontUseSystem =", &useSysFont)) + { + ffPrintError(instance, FF_TERMFONT_MODULE_NAME, 0, &instance->config.terminalFont, "Couldn't open \"$XDG_CONFIG_HOME/xfce4/terminal/terminalrc\""); + ffStrbufDestroy(&useSysFont); + return; + } + + if(useSysFont.length == 0 || ffStrbufIgnCaseCompS(&useSysFont, "FALSE") == 0) + { + printTerminalFontFromConfigFile(instance, "xfce4/terminal/terminalrc", "FontName ="); + ffStrbufDestroy(&useSysFont); + return; + } + + ffStrbufDestroy(&useSysFont); + + 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.terminalFont, "Couldn't find \"xsettings::/Gtk/MonospaceFontName\" in XFConf"); + else + { + FFfont font; + ffFontInitPango(&font, fontName); + ffPrintTerminalFontResult(instance, fontName, &font); + ffFontDestroy(&font); + } +} + +bool ffPrintTerminalFontPlatform(FFinstance* instance, const FFTerminalShellResult* shellInfo) +{ + bool success = true; + if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "konsole") == 0) + printKonsole(instance); + else if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "xfce4-terminal") == 0) + printXCFETerminal(instance); + else if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "lxterminal") == 0) + printTerminalFontFromConfigFile(instance, "lxterminal/lxterminal.conf", "fontname ="); + else if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "tilix") == 0) + printTerminalFontFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile"); + else if(ffStrbufIgnCaseCompS(&shellInfo->terminalProcessName, "gnome-terminal-") == 0) + printTerminalFontFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile"); + else + success = false; + return success; +} diff --git a/src/util/apple/osascript.h b/src/util/apple/osascript.h new file mode 100644 index 0000000000..2c9fe8306b --- /dev/null +++ b/src/util/apple/osascript.h @@ -0,0 +1,10 @@ +#pragma once + +#ifndef FASTFETCH_INCLUDED_osascript +#define FASTFETCH_INCLUDED_osascript + +#include "fastfetch.h" + +bool ffOsascript(const char* input, FFstrbuf* result); + +#endif diff --git a/src/util/apple/osascript.m b/src/util/apple/osascript.m new file mode 100644 index 0000000000..363a50d12d --- /dev/null +++ b/src/util/apple/osascript.m @@ -0,0 +1,17 @@ +#include "osascript.h" + +#import +#import +#import + +bool ffOsascript(const char* input, FFstrbuf* result) { + NSString* appleScript = [NSString stringWithUTF8String: input]; + NSAppleScript* script = [[NSAppleScript alloc] initWithSource:appleScript]; + NSDictionary* errInfo = nil; + NSAppleEventDescriptor* descriptor = [script executeAndReturnError:&errInfo]; + if (errInfo) + return false; + + ffStrbufSetS(result, [[descriptor stringValue] cStringUsingEncoding:NSUTF8StringEncoding]); + return true; +}