#include "fastfetch.h"
#include "common/io/io.h"
#include "common/processing.h"
#include "common/properties.h"
#include "util/stringUtils.h"
#include "util/binary.h"
#include <ctype.h>
#ifdef __FreeBSD__
#include <paths.h>
#ifndef _PATH_LOCALBASE
#define _PATH_LOCALBASE "/usr/local"
#endif
#elif __OpenBSD__
#define _PATH_LOCALBASE "/usr/local"
#elif __NetBSD__
#define _PATH_LOCALBASE "/usr/pkg"
#elif _WIN32
#include "util/windows/version.h"
#include <windows.h>
static bool getFileVersion(const FFstrbuf* exePath, const wchar_t* stringName, FFstrbuf* version)
{
wchar_t exePathW[PATH_MAX + 1];
int len = MultiByteToWideChar(CP_UTF8, 0, exePath->chars, (int)exePath->length, exePathW, ARRAY_SIZE(exePathW));
if (len <= 0) return false;
assert(len < (int) ARRAY_SIZE(exePathW));
exePathW[len] = L'\0';
return ffGetFileVersion(exePathW, stringName, version);
}
#elif __HAIKU__
#include "util/haiku/version.h"
#endif
static bool getExeVersionRaw(FFstrbuf* exe, FFstrbuf* version)
{
return ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) == NULL;
}
static bool getExeVersionGeneral(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version))
return false;
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufSubstrBeforeFirstC(version, ' ');
return true;
}
static bool extractBashVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (!ffStrStartsWith(line, "@(#)Bash version ")) return true;
const char* start = line + strlen("@(#)Bash version ");
const char* end = strchr(start, '(');
if (!end) return true;
ffStrbufSetNS((FFstrbuf*) userdata, (uint32_t) (end - start), start);
return false;
}
static bool getShellVersionBash(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* version)
{
const char* path = exePath->chars;
if (*path == '\0')
path = exe->chars;
ffBinaryExtractStrings(path, extractBashVersion, version, (uint32_t) strlen("@(#)Bash version 0.0.0(0) release GNU"));
if (version->length > 0) return true;
if(!getExeVersionRaw(exe, version))
return false;
ffStrbufSubstrBeforeFirstC(version, '('); ffStrbufSubstrAfterLastC(version, ' '); return true;
}
static bool getShellVersionFish(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version))
return false;
ffStrbufSubstrAfterLastC(version, ' ');
return true;
}
static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
{
const char* env = getenv("POWERSHELL_VERSION");
if (env)
{
ffStrbufSetS(version, env);
return true;
}
#ifdef _WIN32
if(getFileVersion(exe, NULL, version))
{
ffStrbufSubstrBeforeLastC(version, '.');
return true;
}
#endif
if(!getExeVersionRaw(exe, version))
return false;
ffStrbufSubstrAfterLastC(version, ' ');
return true;
}
static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version)
{
#if __OpenBSD__ || __NetBSD__
if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-c",
"echo $KSH_VERSION",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, 'v');
ffStrbufSubstrBeforeFirstC(version, ' ');
#else
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterLastC(version, ')');
ffStrbufTrim(version, ' ');
#endif
return true;
}
static bool getShellVersionOksh(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-c",
"echo $OKSH_VERSION",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, ' ');
return true;
}
static bool getShellVersionOils(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufSubstrBeforeFirstC(version, '\t');
return true;
}
static bool getShellVersionNushell(FFstrbuf* exe, FFstrbuf* version)
{
ffStrbufSetS(version, getenv("NU_VERSION"));
if (version->length) return true;
return getExeVersionRaw(exe, version); }
static bool getShellVersionAsh(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--help",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufSubstrBeforeFirstC(version, ' ');
ffStrbufTrimLeft(version, 'v');
return true;
}
static bool getShellVersionXonsh(FFstrbuf* exe, FFstrbuf* version)
{
ffStrbufSetS(version, getenv("XONSH_VERSION"));
if (version->length) return true;
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, '/');
return true;
}
static bool extractZshVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (!ffStrStartsWith(line, "zsh-")) return true;
const char* start = line + strlen("zsh-");
const char* end = strchr(start, '-');
if (!end) return true;
ffStrbufSetNS((FFstrbuf*) userdata, (uint32_t) (end - start), start);
return false;
}
static bool getShellVersionZsh(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* version)
{
const char* path = exePath->chars;
if (*path == '\0')
path = exe->chars;
ffBinaryExtractStrings(path, extractZshVersion, version, (uint32_t) strlen("zsh-0.0-0"));
if (version->length) return true;
return getExeVersionGeneral(exe, version); }
#ifdef _WIN32
static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
{
const char* env = getenv("POWERSHELL_VERSION");
if (env)
{
ffStrbufSetS(version, env);
return true;
}
return ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-NoLogo",
"-NoProfile",
"-Command",
"$PSVersionTable.PSVersion.ToString()",
NULL
}) == NULL;
}
#endif
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath, FFstrbuf* version)
{
if (!instance.config.general.detectVersion) return false;
if(ffStrEqualsIgnCase(exeName, "sh")) return false;
if(ffStrEqualsIgnCase(exeName, "bash"))
return getShellVersionBash(exe, exePath, version);
if(ffStrEqualsIgnCase(exeName, "zsh"))
return getShellVersionZsh(exe, exePath, version);
if(ffStrEqualsIgnCase(exeName, "fish"))
return getShellVersionFish(exe, version);
if(ffStrEqualsIgnCase(exeName, "pwsh"))
return getShellVersionPwsh(exe, version);
if(ffStrEqualsIgnCase(exeName, "csh") || ffStrEqualsIgnCase(exeName, "tcsh"))
return getExeVersionGeneral(exe, version); if(ffStrEqualsIgnCase(exeName, "nu"))
return getShellVersionNushell(exe, version);
if(ffStrEqualsIgnCase(exeName, "ksh"))
return getShellVersionKsh(exe, version);
if(ffStrEqualsIgnCase(exeName, "oksh"))
return getShellVersionOksh(exe, version);
if(ffStrEqualsIgnCase(exeName, "oil.ovm"))
return getShellVersionOils(exe, version);
if(ffStrEqualsIgnCase(exeName, "elvish"))
return getExeVersionRaw(exe, version);
if(ffStrEqualsIgnCase(exeName, "ash"))
return getShellVersionAsh(exe, version);
if(ffStrEqualsIgnCase(exeName, "xonsh"))
return getShellVersionXonsh(exe, version);
#ifdef _WIN32
if(ffStrEqualsIgnCase(exeName, "powershell") || ffStrEqualsIgnCase(exeName, "powershell_ise"))
return getShellVersionWinPowerShell(exe, version);
return getFileVersion(exe, NULL, version);
#endif
return false;
}
FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version)
{
ffStrbufSetS(version, getenv("TERMUX_VERSION"));
return version->length > 0;
}
static bool extractGeneralVersion(const char *str, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (!ffCharIsDigit(str[0])) return true;
int count = 0;
sscanf(str, "%*d.%*d.%*d%n", &count);
if (count == 0) return true;
ffStrbufSetS((FFstrbuf*) userdata, str);
return false;
}
FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* exe, FFstrbuf* version)
{
if (exe->chars[0] == '/')
{
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
if (version->length) return true;
}
if(ffProcessAppendStdOut(version, (char* const[]){
"gnome-terminal",
"--version",
NULL
})) return false;
ffStrbufSubstrAfterFirstS(version, "Terminal ");
ffStrbufSubstrBeforeFirstC(version, ' ');
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionXfce4Terminal(FFstrbuf* exe, FFstrbuf* version)
{
if (exe->chars[0] == '/')
{
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
if (version->length) return true;
}
return getExeVersionGeneral(exe, version);}
FF_MAYBE_UNUSED static bool getTerminalVersionKgx(FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]){
"kgx",
"--version",
NULL
})) return false;
ffStrbufSubstrAfterFirstS(version, "KGX ");
ffStrbufSubstrBeforeFirstC(version, ' ');
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* version)
{
const char* konsoleVersion = getenv("KONSOLE_VERSION");
if(konsoleVersion)
{
long major = strtol(konsoleVersion, NULL, 10);
if (major >= 0)
{
long patch = major % 100;
major /= 100;
long minor = major % 100;
major /= 100;
ffStrbufSetF(version, "%ld.%ld.%ld", major, minor, patch);
return true;
}
}
return getExeVersionGeneral(exe, version);
}
FF_MAYBE_UNUSED static bool getTerminalVersionFoot(FFstrbuf* exe, FFstrbuf* version)
{
uint32_t major = 0, minor = 0, patch = 0;
if (ffGetTerminalResponse("\e[>c", 3, "\e[>1;%2u%2u%2u;0c", &major, &minor, &patch) == NULL)
{
ffStrbufSetF(version, "%u.%u.%u", major, minor, patch);
return true;
}
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrAfterFirstS(version, "version: ");
ffStrbufSubstrBeforeFirstC(version, ' ');
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionMateTerminal(FFstrbuf* exe, FFstrbuf* version)
{
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
if (version->length > 0) return true;
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrAfterLastC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionCockpit(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrBeforeFirstC(version, '\n');
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionXterm(FFstrbuf* exe, FFstrbuf* version)
{
ffStrbufSetS(version, getenv("XTERM_VERSION"));
if (!version->length)
{
if(ffProcessAppendStdOut(version, (char* const[]){
exe->chars,
"-v",
NULL
})) return false;
}
ffStrbufTrimRight(version, ')');
ffStrbufSubstrAfterFirstC(version, '(');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionBlackbox(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]){
exe->chars,
"--version",
NULL
})) return false;
ffStrbufSubstrAfterFirstS(version, "version ");
ffStrbufSubstrBeforeFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionUrxvt(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]){
"urxvt", "-invalid",
NULL
})) return false;
ffStrbufSubstrAfterFirstS(version, "(urxvt) v");
ffStrbufSubstrBeforeFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionSt(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]){
exe->chars,
"-v",
NULL
})) return false;
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionLxterminal(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionWeston(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]){
"weston",
"--version",
NULL
})) return false;
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version)
{
const char* env = getenv("TERMINAL_VERSION_STRING");
if (env)
{
ffStrbufAppendS(version, env);
return true;
}
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrAfterLastC(version, ' ');
return version->length > 0;
}
static bool getTerminalVersionScreen(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrAfter(version, (uint32_t) strlen("Screen version ") - 1);
ffStrbufSubstrBeforeFirstC(version, ' ');
return version->length > 0;
}
static bool getTerminalVersionTmux(FFstrbuf* exe, FFstrbuf* version)
{
if (ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-V",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
static bool getTerminalVersionZellij(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version)) return false;
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version)
{
FF_STRBUF_AUTO_DESTROY cli = ffStrbufCreateCopy(exe);
ffStrbufSubstrBeforeLastC(&cli, '/');
ffStrbufAppendS(&cli, "/cli"
#ifdef _WIN32
".exe"
#endif
);
if(ffProcessAppendStdOut(version, (char* const[]) {
cli.chars,
"--version",
NULL
}) != NULL)
return false;
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufSubstrBeforeFirstC(version, ' ');
return true;
}
#ifndef _WIN32
static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
{
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
char buffer[1024] = {};
if (
#ifdef __linux__
ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) ||
ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer)
#else
ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer)
#endif
)
{
const char* p = memmem(buffer, ARRAY_SIZE(buffer) - 1, "version: Version = Version(", strlen("version: Version = Version("));
if (p)
{
p += strlen("version: Version = Version(");
int major, minor, patch;
if (sscanf(p, "%d,%d,%d", &major, &minor, &patch) == 3)
{
ffStrbufSetF(version, "%d.%d.%d", major, minor, patch);
return true;
}
}
}
#elif __APPLE__
if (ffStrbufEndsWithS(exe, "/kitty.app/Contents/MacOS/kitty"))
{
ffStrbufSet(version, exe);
ffStrbufSubstrBeforeLastC(version, '/');
ffStrbufSubstrBeforeLastC(version, '/');
ffStrbufAppendS(version, "/Info.plist");
char buf[4096];
ssize_t size = ffReadFileData(version->chars, ARRAY_SIZE(buf) - 1, buf);
if (size > 0)
{
buf[size] = '\0';
const char* p = strstr(buf, "<key>CFBundleShortVersionString</key>");
if (p)
{
p += strlen("<key>CFBundleShortVersionString</key>");
p = strchr(p, '>');
if (p)
{
p++;
const char* end = strchr(p, '<');
if (end)
{
ffStrbufSetNS(version, (uint32_t) (end - p), p);
return true;
}
}
}
}
ffStrbufClear(version);
}
#endif
char versionHex[64];
if (ffGetTerminalResponse(
"\eP+q6b697474792d71756572792d76657273696f6e\e\\", 1,
"\eP1+r%*[^=]=%63[^\e]\e\\\\", versionHex) == NULL)
{
for (const char* p = versionHex; p[0] && p[1]; p += 2)
{
unsigned value;
if (sscanf(p, "%2x", &value) == 1)
ffStrbufAppendC(version, (char) value);
}
return true;
}
return getExeVersionGeneral(exe, version);
}
FF_MAYBE_UNUSED static bool getTerminalVersionPtyxis(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]) {
"ptyxis",
"--version",
NULL
}) != NULL)
return false;
ffStrbufSubstrBeforeFirstC(version, '\n');
ffStrbufSubstrAfterFirstC(version, ' ');
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* version)
{
if (exe->chars[0] == '/')
{
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
if (version->length) return true;
}
if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL)
return false;
uint32_t index = ffStrbufFirstIndexS(version, "Tilix version: ");
if (index == version->length) return false;
index += (uint32_t) strlen("Tilix version:");
uint32_t end = ffStrbufNextIndexC(version, index, '\n');
ffStrbufSubstrBefore(version, end);
ffStrbufSubstrAfter(version, index);
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionSakura(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL) return false;
ffStrbufSubstrAfterLastC(version, ' ');
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionTermite(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL) return false;
ffStrbufSubstrBeforeFirstC(version, '\n');
ffStrbufSubstrAfterLastC(version, 'v');
return true;
}
#endif
#ifdef _WIN32
static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
{
FF_STRBUF_AUTO_DESTROY buildInfoPath;
ffStrbufInitNS(&buildInfoPath, ffStrbufLastIndexC(exe, '\\') + 1, exe->chars);
ffStrbufAppendS(&buildInfoPath, "BuildInfo.xml");
if(ffParsePropFile(buildInfoPath.chars, "StoreVersion=\"", version))
{
ffStrbufTrimRight(version, '"');
return true;
}
return getFileVersion(exe, NULL, version);
}
static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
{
ffStrbufSetS(version, getenv("ConEmuBuild"));
if(version->length)
return true;
return getFileVersion(exe, NULL, version);
}
#endif
bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
if (!instance.config.general.detectVersion) return false;
#ifdef __ANDROID__
if(ffStrbufEqualS(processName, "com.termux"))
return getTerminalVersionTermux(version);
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__HAIKU__)
if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal"))
return getTerminalVersionGnome(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "konsole"))
return getTerminalVersionKonsole(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "yakuake"))
return getTerminalVersionKonsole(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal"))
return getTerminalVersionXfce4Terminal(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "terminator"))
return getExeVersionGeneral(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "deepin-terminal"))
return getExeVersionGeneral(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "foot"))
return getTerminalVersionFoot(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "qterminal"))
return getExeVersionRaw(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "mate-terminal"))
return getTerminalVersionMateTerminal(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "cockpit-bridge"))
return getTerminalVersionCockpit(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "xterm"))
return getTerminalVersionXterm(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "blackbox"))
return getTerminalVersionBlackbox(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "st"))
return getTerminalVersionSt(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "lxterminal"))
return getTerminalVersionLxterminal(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "weston-terminal"))
return getTerminalVersionWeston(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "urxvt") ||
ffStrbufIgnCaseEqualS(processName, "urxvtd") ||
ffStrbufIgnCaseEqualS(processName, "rxvt") ||
ffStrbufIgnCaseEqualS(processName, "rxvt-unicode")
)
return getTerminalVersionUrxvt(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "ptyxis-agent"))
return getTerminalVersionPtyxis(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "tilix"))
return getTerminalVersionTilix(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "sakura"))
return getTerminalVersionSakura(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "termite"))
return getTerminalVersionTermite(exe, version);
#endif
#ifdef _WIN32
if(ffStrbufIgnCaseEqualS(processName, "WindowsTerminal.exe"))
return getTerminalVersionWindowsTerminal(exe, version);
if(ffStrbufStartsWithIgnCaseS(processName, "ConEmu"))
return getTerminalVersionConEmu(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "warp.exe"))
return getFileVersion(exe, L"ProductVersion", version);
#endif
#ifndef _WIN32
if(ffStrbufIgnCaseEqualS(processName, "kitty"))
return getTerminalVersionKitty(exe, version);
if (ffStrbufIgnCaseEqualS(processName, "Tabby") && getExeVersionRaw(exe, version))
return true;
#endif
if(ffStrbufStartsWithIgnCaseS(processName, "alacritty"))
return getExeVersionGeneral(exe, version);
if(ffStrbufStartsWithIgnCaseS(processName, "contour"))
return getTerminalVersionContour(exe, version);
if(ffStrbufStartsWithIgnCaseS(processName, "screen"))
return getTerminalVersionScreen(exe, version);
if(ffStrbufStartsWithIgnCaseS(processName, "zellij"))
return getTerminalVersionZellij(exe, version);
if(ffStrbufStartsWithIgnCaseS(processName, "zed"))
return getTerminalVersionZed(exe, version);
#if __HAIKU__
if(ffStrbufEqualS(processName, "Terminal"))
return ffGetFileVersion(exe->chars, version);
#endif
const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION");
if(termProgramVersion)
{
const char* termProgram = getenv("TERM_PROGRAM");
if(termProgram)
{
if(ffStrbufStartsWithIgnCaseS(processName, termProgram) || (ffStrEquals(termProgram, "vscode") && ffStrbufStartsWithIgnCaseS(processName, "code")) ||
#ifdef __APPLE__
(ffStrEquals(termProgram, "iTerm.app") && ffStrbufStartsWithIgnCaseS(processName, "iTermServer-")) ||
#elif defined(__linux__)
(ffStrEquals(termProgram, "WarpTerminal") && ffStrbufEqualS(processName, "warp")) ||
#endif
false
) {
ffStrbufSetS(version, termProgramVersion);
return true;
}
}
}
termProgramVersion = getenv("LC_TERMINAL_VERSION");
if(termProgramVersion)
{
const char* termProgram = getenv("LC_TERMINAL");
if(termProgram)
{
if(ffStrbufStartsWithIgnCaseS(processName, termProgram) || (ffStrEquals(termProgram, "vscode") && ffStrbufStartsWithIgnCaseS(processName, "code")) ||
(ffStrStartsWith(termProgram, "iTerm") && ffStrbufStartsWithIgnCaseS(processName, "iTermServer-"))
) {
ffStrbufSetS(version, termProgramVersion);
return true;
}
}
}
if(ffStrbufStartsWithIgnCaseS(processName, "tmux"))
return getTerminalVersionTmux(exe, version);
#ifdef _WIN32
return getFileVersion(exe, NULL, version);
#else
return false;
#endif
}