mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Merge pull request #254 from CarterLi/master
TerminalFont: support Windows Terminal on WSL
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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//
|
||||
|
||||
@@ -150,6 +150,7 @@ typedef struct FFconfig
|
||||
FFstrbuf libOSMesa;
|
||||
FFstrbuf libOpenCL;
|
||||
FFstrbuf libplist;
|
||||
FFstrbuf libcJSON;
|
||||
|
||||
bool titleFQDN;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user