Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@v3

- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev

- name: Initialize CodeQL
uses: github/codeql-action/init@v2
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_LIBPLIST "Enable libplist" ON "APPLE" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX" OFF)

option(BUILD_TESTS "Build tests" OFF) # Also create test executables
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
Expand Down Expand Up @@ -375,6 +376,7 @@ ff_lib_enable(GLX glx)
ff_lib_enable(OSMESA osmesa)
ff_lib_enable(OPENCL OpenCL)
ff_lib_enable(LIBPLIST libplist-2.0)
ff_lib_enable(LIBCJSON libcjson)

if(APPLE)
target_link_libraries(libfastfetch
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ The following libraries are used if present at runtime:
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
* [`libplist`](https://github.com/libimobiledevice/libplist): Binary `plist` file parser ( macOS ). Needed for iTerm2 Terminal font and WM Theme.
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).

## Support status
All categories not listed here should work without needing a specific implementation.
Expand Down Expand Up @@ -81,7 +82,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt

##### Terminal fonts
```
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal
```

## Building
Expand Down
1 change: 1 addition & 0 deletions src/common/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.libOSMesa, 0);
ffStrbufInitA(&instance->config.libOpenCL, 0);
ffStrbufInitA(&instance->config.libplist, 0);
ffStrbufInitA(&instance->config.libcJSON, 0);

instance->config.titleFQDN = false;

Expand Down
1 change: 1 addition & 0 deletions src/data/config_user.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,4 @@
#--lib-osmesa /usr/lib/libOSMesa.so
#--lib-opencl /usr/lib/libOpenCL.so
#--lib-plist /usr/local/bin/libplist-2.0.dylib
#--lib-cjson /usr/lib/libcjson.so
1 change: 1 addition & 0 deletions src/data/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Library options: Set the path of a library to load
--lib-osmesa <path>
--lib-opencl <path>
--lib-plist <path>
--lib-cjson <path>

Module specific options:
--title-fqdn <?value>: Sets if the title should use fully qualified domain name. Default is false.
Expand Down
8 changes: 8 additions & 0 deletions src/detection/terminalShell.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
if(!ffStrSet(term))
term = getenv("TERM_PROGRAM");

//We are in WSL but not in Windows Terminal
if(!ffStrSet(term) && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
))
term = "conhost";

//Normal Terminal
if(!ffStrSet(term))
term = getenv("TERM");
Expand Down
17 changes: 12 additions & 5 deletions src/detection/terminalfont/terminalfont_apple.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ static const char* iterm2ParsePList(const FFinstance* instance, const FFstrbuf*
else
ffplist_from_xml(content->chars, content->length, &root_node);

const char* error = NULL;

if(root_node == NULL)
return "parsing iTerm preference file failed";
{
error = "parsing iTerm preference file failed";
goto exit;
}

plist_t bookmarks = ffplist_access_path(root_node, 1, "New Bookmarks");

Expand All @@ -50,20 +55,22 @@ static const char* iterm2ParsePList(const FFinstance* instance, const FFstrbuf*

if(item == NULL)
{
ffplist_free(root_node);
return "find profile bookmark failed";
error = "find profile bookmark failed";
goto exit;
}

item = ffplist_dict_get_item(item, "Normal Font");
if (item == NULL)
{
ffplist_free(root_node);
return "find Normal Font key failed";
error = "find Normal Font key failed";
goto exit;
}

ffFontInitWithSpace(&terminalFont->font, ffplist_get_string_ptr(item, NULL));

exit:
ffplist_free(root_node);
dlclose(libplist);
return NULL;
}

Expand Down
174 changes: 174 additions & 0 deletions src/detection/terminalfont/terminalfont_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,178 @@ static void detectXFCETerminal(const FFinstance* instance, FFTerminalFontResult*
ffStrbufDestroy(&useSysFont);
}

#ifdef FF_HAVE_LIBCJSON

#include "common/library.h"
#include "common/processing.h"

#include <cjson/cJSON.h>
#include <stdlib.h>

typedef struct CJSONData
{
FF_LIBRARY_SYMBOL(cJSON_Parse)
FF_LIBRARY_SYMBOL(cJSON_IsObject)
FF_LIBRARY_SYMBOL(cJSON_GetObjectItemCaseSensitive)
FF_LIBRARY_SYMBOL(cJSON_IsString)
FF_LIBRARY_SYMBOL(cJSON_GetStringValue)
FF_LIBRARY_SYMBOL(cJSON_IsNumber)
FF_LIBRARY_SYMBOL(cJSON_GetNumberValue)
FF_LIBRARY_SYMBOL(cJSON_IsArray)
FF_LIBRARY_SYMBOL(cJSON_Delete)
} CJSONData;

static const char* detectWTProfile(CJSONData* cjsonData, cJSON* profile, FFstrbuf* name, int* size)
{
if(!cjsonData->ffcJSON_IsObject(profile))
return "cJSON_IsObject(profile) returns false";

cJSON* font = cjsonData->ffcJSON_GetObjectItemCaseSensitive(profile, "font");
if(!cjsonData->ffcJSON_IsObject(font))
return "cJSON_IsObject(font) returns false";

if(name->length == 0)
{
cJSON* pface = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "face");
if(cjsonData->ffcJSON_IsString(pface))
ffStrbufAppendS(name, cjsonData->ffcJSON_GetStringValue(pface));
}
if(*size < 0)
{
cJSON* psize = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "size");
if(cjsonData->ffcJSON_IsNumber(psize))
*size = (int)cjsonData->ffcJSON_GetNumberValue(psize);
}
return NULL;
}

static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* content, FFstrbuf* name, int* size)
{
CJSONData cjsonData;

FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson failed", "libcjson"FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete)

const char* error = NULL;

cJSON* root = cjsonData.ffcJSON_Parse(content->chars);
if(!cjsonData.ffcJSON_IsObject(root))
{
error = "cJSON_Parse() failed";
goto exit;
}

cJSON* profiles = cjsonData.ffcJSON_GetObjectItemCaseSensitive(root, "profiles");
if(!cjsonData.ffcJSON_IsObject(profiles))
{
error = "cJSON_GetObjectItemCaseSensitive(root, \"profiles\") failed";
goto exit;
}

FFstrbuf wtProfileId;
ffStrbufInitS(&wtProfileId, getenv("WT_PROFILE_ID"));
ffStrbufTrim(&wtProfileId, '\'');
if(wtProfileId.length > 0)
{
cJSON* list = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "list");
if(cjsonData.ffcJSON_IsArray(list))
{
cJSON* profile;
cJSON_ArrayForEach(profile, list)
{
if(!cjsonData.ffcJSON_IsObject(profile))
continue;
cJSON* guid = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profile, "guid");
if(!cjsonData.ffcJSON_IsString(guid))
continue;
if(ffStrbufCompS(&wtProfileId, cjsonData.ffcJSON_GetStringValue(guid)) == 0)
{
detectWTProfile(&cjsonData, profile, name, size);
break;
}
}
}
}
ffStrbufDestroy(&wtProfileId);

cJSON* defaults = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "defaults");
detectWTProfile(&cjsonData, defaults, name, size);

if(name->length == 0)
ffStrbufSetS(name, "Cascadia Mono");
if(*size < 0)
*size = 12;

exit:
cjsonData.ffcJSON_Delete(root);
dlclose(libcjson);
return error;
}

static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont)
{
//https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file
FFstrbuf json;
ffStrbufInit(&json);
const char* error;
error = ffProcessAppendStdOut(&json, (char* const[]) {
"cmd.exe",
"/c",
//print the file content directly, so we don't need to handle the difference of Windows and POSIX path
"if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json "
"( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json ) "
"else if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json "
"( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json ) "
"else if exist \"%LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json\" "
"( type %LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json ) "
"else ( call )",
NULL
});
if(error)
{
ffStrbufAppendS(&terminalFont->error, error);
ffStrbufDestroy(&json);
return;
}
ffStrbufTrimRight(&json, '\n');
if(json.length == 0)
{
ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\"");
ffStrbufDestroy(&json);
return;
}

FFstrbuf name;
ffStrbufInit(&name);
int size = -1;
detectFromWTImpl(instance, &json, &name, &size);
ffStrbufDestroy(&json);

char sizeStr[16];
snprintf(sizeStr, sizeof(sizeStr), "%d", size);
ffFontInitValues(&terminalFont->font, name.chars, sizeStr);

ffStrbufDestroy(&name);
}

#else

static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont)
{
FF_UNUSED(instance, terminalFont);
ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support");
}

#endif

void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0)
Expand All @@ -152,4 +324,6 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh
detectFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "gnome-terminal-") == 0)
detectFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0)
detectFromWindowsTeriminal(instance, terminalFont);
}
2 changes: 2 additions & 0 deletions src/fastfetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.libOpenCL);
else if(strcasecmp(key, "--lib-plist") == 0)
optionParseString(key, value, &instance->config.libplist);
else if(strcasecmp(key, "--lib-cjson") == 0)
optionParseString(key, value, &instance->config.libcJSON);

//////////////////
//Module options//
Expand Down
1 change: 1 addition & 0 deletions src/fastfetch.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ typedef struct FFconfig
FFstrbuf libOSMesa;
FFstrbuf libOpenCL;
FFstrbuf libplist;
FFstrbuf libcJSON;

bool titleFQDN;

Expand Down