TerminalShell: split terminal and shell detection code further

This commit is contained in:
李通洲
2024-01-12 20:42:33 +08:00
parent 6da57d64c3
commit 905ed76ddd
12 changed files with 365 additions and 322 deletions
+107 -91
View File
@@ -118,7 +118,7 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
return NULL;
}
static pid_t getShellInfo(FFTerminalShellResult* result, pid_t pid)
static pid_t getShellInfo(FFShellResult* result, pid_t pid)
{
char name[256];
name[0] = '\0';
@@ -148,13 +148,14 @@ static pid_t getShellInfo(FFTerminalShellResult* result, pid_t pid)
)
return getShellInfo(result, ppid);
result->shellPid = (uint32_t) pid;
ffStrbufSetS(&result->shellProcessName, name);
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
result->pid = (uint32_t) pid;
result->ppid = (uint32_t) ppid;
ffStrbufSetS(&result->processName, name);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName);
return ppid;
}
static pid_t getTerminalInfo(FFTerminalShellResult* result, pid_t pid)
static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
{
char name[256];
name[0] = '\0';
@@ -191,29 +192,29 @@ static pid_t getTerminalInfo(FFTerminalShellResult* result, pid_t pid)
getProcessNameAndPpid(ppid, name, &ppid);
#endif
result->terminalPid = (uint32_t) pid;
ffStrbufSetS(&result->terminalProcessName, name);
getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName);
result->pid = (uint32_t) pid;
ffStrbufSetS(&result->processName, name);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName);
return ppid;
}
static void getTerminalFromEnv(FFTerminalShellResult* result)
static void getTerminalFromEnv(FFTerminalResult* result)
{
if(
result->terminalProcessName.length > 0 &&
!ffStrbufStartsWithIgnCaseS(&result->terminalProcessName, "login") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(login)") &&
result->processName.length > 0 &&
!ffStrbufStartsWithIgnCaseS(&result->processName, "login") &&
!ffStrbufIgnCaseEqualS(&result->processName, "(login)") &&
#ifdef __APPLE__
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "launchd") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "stable") && //for WarpTerminal
!ffStrbufIgnCaseEqualS(&result->processName, "launchd") &&
!ffStrbufIgnCaseEqualS(&result->processName, "stable") && //for WarpTerminal
#else
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "systemd") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "init") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(init)") &&
!ffStrbufIgnCaseEqualS(&result->processName, "systemd") &&
!ffStrbufIgnCaseEqualS(&result->processName, "init") &&
!ffStrbufIgnCaseEqualS(&result->processName, "(init)") &&
#endif
ffStrbufIgnCaseCompS(&result->terminalProcessName, "0") != 0
ffStrbufIgnCaseCompS(&result->processName, "0") != 0
) return;
const char* term = NULL;
@@ -274,20 +275,20 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
if(ffStrSet(term))
{
ffStrbufSetS(&result->terminalProcessName, term);
ffStrbufSetS(&result->terminalExe, term);
setExeName(&result->terminalExe, &result->terminalExeName);
ffStrbufSetS(&result->processName, term);
ffStrbufSetS(&result->exe, term);
setExeName(&result->exe, &result->exeName);
}
}
static void getUserShellFromEnv(FFTerminalShellResult* result)
static void getUserShellFromEnv(FFShellResult* result)
{
//If shell detection via processes failed
if(result->shellProcessName.length == 0 && instance.state.platform.userShell.length > 0)
if(result->processName.length == 0 && instance.state.platform.userShell.length > 0)
{
ffStrbufSet(&result->shellExe, &instance.state.platform.userShell);
setExeName(&result->shellExe, &result->shellExeName);
ffStrbufAppendS(&result->shellProcessName, result->shellExeName);
ffStrbufSet(&result->exe, &instance.state.platform.userShell);
setExeName(&result->exe, &result->exeName);
ffStrbufAppendS(&result->processName, result->exeName);
}
}
@@ -295,114 +296,129 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
static void setShellInfoDetails(FFTerminalShellResult* result)
static void setShellInfoDetails(FFShellResult* result)
{
ffStrbufClear(&result->shellVersion);
fftsGetShellVersion(&result->shellExe, result->shellExeName, &result->shellVersion);
ffStrbufClear(&result->version);
fftsGetShellVersion(&result->exe, result->exeName, &result->version);
if(ffStrbufEqualS(&result->shellProcessName, "pwsh"))
ffStrbufInitStatic(&result->shellPrettyName, "PowerShell");
else if(ffStrbufEqualS(&result->shellProcessName, "nu"))
ffStrbufInitStatic(&result->shellPrettyName, "nushell");
else if(ffStrbufIgnCaseEqualS(&result->shellProcessName, "python") && getenv("XONSH_VERSION"))
ffStrbufInitStatic(&result->shellPrettyName, "xonsh");
else if(ffStrbufIgnCaseEqualS(&result->shellProcessName, "oil.ovm"))
ffStrbufInitStatic(&result->shellPrettyName, "Oils");
if(ffStrbufEqualS(&result->processName, "pwsh"))
ffStrbufInitStatic(&result->prettyName, "PowerShell");
else if(ffStrbufEqualS(&result->processName, "nu"))
ffStrbufInitStatic(&result->prettyName, "nushell");
else if(ffStrbufIgnCaseEqualS(&result->processName, "python") && getenv("XONSH_VERSION"))
ffStrbufInitStatic(&result->prettyName, "xonsh");
else if(ffStrbufIgnCaseEqualS(&result->processName, "oil.ovm"))
ffStrbufInitStatic(&result->prettyName, "Oils");
else
{
// https://github.com/fastfetch-cli/fastfetch/discussions/280#discussioncomment-3831734
ffStrbufInitS(&result->shellPrettyName, result->shellExeName);
ffStrbufInitS(&result->prettyName, result->exeName);
}
}
static void setTerminalInfoDetails(FFTerminalShellResult* result)
static void setTerminalInfoDetails(FFTerminalResult* result)
{
if(result->terminalExeName[0] == '.' && ffStrEndsWith(result->terminalExeName, "-wrapped"))
if(result->exeName[0] == '.' && ffStrEndsWith(result->exeName, "-wrapped"))
{
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
// We use terminalProcessName when detecting version and font, overriding it for simplification
// We use processName when detecting version and font, overriding it for simplification
ffStrbufSetNS(
&result->terminalProcessName,
(uint32_t) (strlen(result->terminalExeName) - strlen(".-wrapped")),
result->terminalExeName + 1);
&result->processName,
(uint32_t) (strlen(result->exeName) - strlen(".-wrapped")),
result->exeName + 1);
}
if(ffStrbufEqualS(&result->terminalProcessName, "wezterm-gui"))
ffStrbufInitStatic(&result->terminalPrettyName, "WezTerm");
if(ffStrbufStartsWithS(&result->terminalProcessName, "tmux:"))
ffStrbufInitStatic(&result->terminalPrettyName, "tmux");
if(ffStrbufEqualS(&result->processName, "wezterm-gui"))
ffStrbufInitStatic(&result->prettyName, "WezTerm");
if(ffStrbufStartsWithS(&result->processName, "tmux:"))
ffStrbufInitStatic(&result->prettyName, "tmux");
#if defined(__ANDROID__)
else if(ffStrbufEqualS(&result->terminalProcessName, "com.termux"))
ffStrbufInitStatic(&result->terminalPrettyName, "Termux");
else if(ffStrbufEqualS(&result->processName, "com.termux"))
ffStrbufInitStatic(&result->prettyName, "Termux");
#elif defined(__linux__) || defined(__FreeBSD__)
else if(ffStrbufStartsWithS(&result->terminalProcessName, "gnome-terminal-"))
ffStrbufInitStatic(&result->terminalPrettyName, "GNOME Terminal");
else if(ffStrbufStartsWithS(&result->terminalProcessName, "kgx"))
ffStrbufInitStatic(&result->terminalPrettyName, "GNOME Console");
else if(ffStrbufEqualS(&result->terminalProcessName, "urxvt") ||
ffStrbufEqualS(&result->terminalProcessName, "urxvtd") ||
ffStrbufEqualS(&result->terminalProcessName, "rxvt")
else if(ffStrbufStartsWithS(&result->processName, "gnome-terminal-"))
ffStrbufInitStatic(&result->prettyName, "GNOME Terminal");
else if(ffStrbufStartsWithS(&result->processName, "kgx"))
ffStrbufInitStatic(&result->prettyName, "GNOME Console");
else if(ffStrbufEqualS(&result->processName, "urxvt") ||
ffStrbufEqualS(&result->processName, "urxvtd") ||
ffStrbufEqualS(&result->processName, "rxvt")
)
ffStrbufInitStatic(&result->terminalPrettyName, "rxvt-unicode");
ffStrbufInitStatic(&result->prettyName, "rxvt-unicode");
#elif defined(__APPLE__)
else if(ffStrbufEqualS(&result->terminalProcessName, "iTerm.app") || ffStrbufStartsWithS(&result->terminalProcessName, "iTermServer-"))
ffStrbufInitStatic(&result->terminalPrettyName, "iTerm");
else if(ffStrbufEqualS(&result->terminalProcessName, "Apple_Terminal"))
ffStrbufInitStatic(&result->terminalPrettyName, "Apple Terminal");
else if(ffStrbufEqualS(&result->terminalProcessName, "WarpTerminal"))
ffStrbufInitStatic(&result->terminalPrettyName, "Warp");
else if(ffStrbufEqualS(&result->processName, "iTerm.app") || ffStrbufStartsWithS(&result->processName, "iTermServer-"))
ffStrbufInitStatic(&result->prettyName, "iTerm");
else if(ffStrbufEqualS(&result->processName, "Apple_Terminal"))
ffStrbufInitStatic(&result->prettyName, "Apple Terminal");
else if(ffStrbufEqualS(&result->processName, "WarpTerminal"))
ffStrbufInitStatic(&result->prettyName, "Warp");
#endif
else if(strncmp(result->terminalExeName, result->terminalProcessName.chars, result->terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
ffStrbufInitS(&result->terminalPrettyName, result->terminalExeName);
else if(strncmp(result->exeName, result->processName.chars, result->processName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
ffStrbufInitS(&result->prettyName, result->exeName);
else
ffStrbufInitCopy(&result->terminalPrettyName, &result->terminalProcessName);
ffStrbufInitCopy(&result->prettyName, &result->processName);
ffStrbufInit(&result->terminalVersion);
fftsGetTerminalVersion(&result->terminalProcessName, &result->terminalExe, &result->terminalVersion);
ffStrbufInit(&result->version);
fftsGetTerminalVersion(&result->processName, &result->exe, &result->version);
}
const FFTerminalShellResult* ffDetectTerminalShell()
#ifdef __APPLE__
#define FF_EXE_PATH_LEN PROC_PIDPATHINFO_MAXSIZE
#elif defined(MAXPATH)
#define FF_EXE_PATH_LEN MAXPATH
#elif defined(PATH_MAX)
#define FF_EXE_PATH_LEN PATH_MAX
#else
#define FF_EXE_PATH_LEN 260
#endif
const FFShellResult* ffDetectShell()
{
static FFTerminalShellResult result;
static FFShellResult result;
static bool init = false;
if(init)
return &result;
init = true;
#ifdef __APPLE__
const uint32_t exePathLen = PROC_PIDPATHINFO_MAXSIZE;
#elif defined(MAXPATH)
const uint32_t exePathLen = MAXPATH;
#elif defined(PATH_MAX)
const uint32_t exePathLen = PATH_MAX;
#else
const uint32_t exePathLen = 260;
#endif
ffStrbufInit(&result.shellProcessName);
ffStrbufInitA(&result.shellExe, exePathLen);
result.shellExeName = result.shellExe.chars;
ffStrbufInit(&result.shellVersion);
result.shellPid = 0;
ffStrbufInit(&result.terminalProcessName);
ffStrbufInitA(&result.terminalExe, exePathLen);
result.terminalExeName = result.terminalExe.chars;
result.terminalPid = 0;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, FF_EXE_PATH_LEN);
result.exeName = result.exe.chars;
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
pid_t ppid = getppid();
ppid = getShellInfo(&result, ppid);
getUserShellFromEnv(&result);
setShellInfoDetails(&result);
return &result;
}
const FFTerminalResult* ffDetectTerminal()
{
static FFTerminalResult result;
static bool init = false;
if(init)
return &result;
init = true;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, FF_EXE_PATH_LEN);
result.exeName = result.exe.chars;
result.pid = 0;
result.ppid = 0;
pid_t ppid = (pid_t) ffDetectShell()->ppid;
if (ppid)
ppid = getTerminalInfo(&result, ppid);
getTerminalFromEnv(&result);