i forgor 💀
This commit is contained in:
parent
a06b940892
commit
55f0027969
4 changed files with 250 additions and 111 deletions
13
meson.build
13
meson.build
|
@ -5,7 +5,7 @@ project(
|
||||||
default_options: [
|
default_options: [
|
||||||
'default_library=static',
|
'default_library=static',
|
||||||
'warning_level=everything',
|
'warning_level=everything',
|
||||||
'buildtype=debugoptimized',
|
'buildtype=release',
|
||||||
'cpp_args=-fvisibility=hidden',
|
'cpp_args=-fvisibility=hidden',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -49,6 +49,7 @@ common_cpp_args = [
|
||||||
'-Wunused-function',
|
'-Wunused-function',
|
||||||
'-fno-strict-enums',
|
'-fno-strict-enums',
|
||||||
'-nostdlib++',
|
'-nostdlib++',
|
||||||
|
'-march=native',
|
||||||
]
|
]
|
||||||
|
|
||||||
if host_machine.system() == 'windows'
|
if host_machine.system() == 'windows'
|
||||||
|
@ -130,9 +131,11 @@ deps += ftxui_dep
|
||||||
|
|
||||||
cmake_opts = cmake.subproject_options()
|
cmake_opts = cmake.subproject_options()
|
||||||
|
|
||||||
cmake_opts.add_cmake_defines({
|
cmake_opts.add_cmake_defines(
|
||||||
'CMAKE_CXX_FLAGS': '-Wno-everything',
|
{
|
||||||
})
|
'CMAKE_CXX_FLAGS': '-Wno-everything',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
cmake_opts.append_compile_args('cpp', '-Wno-everything')
|
cmake_opts.append_compile_args('cpp', '-Wno-everything')
|
||||||
|
|
||||||
|
@ -153,4 +156,4 @@ executable(
|
||||||
objc_args: objc_args,
|
objc_args: objc_args,
|
||||||
link_args: link_args,
|
link_args: link_args,
|
||||||
dependencies: deps,
|
dependencies: deps,
|
||||||
)
|
)
|
||||||
|
|
171
src/main.cpp
171
src/main.cpp
|
@ -26,7 +26,8 @@ template <>
|
||||||
struct fmt::formatter<BytesToGiB> : fmt::formatter<double> {
|
struct fmt::formatter<BytesToGiB> : fmt::formatter<double> {
|
||||||
template <typename FmtCtx>
|
template <typename FmtCtx>
|
||||||
constexpr fn format(const BytesToGiB& BTG, FmtCtx& ctx) const -> typename FmtCtx::iterator {
|
constexpr fn format(const BytesToGiB& BTG, FmtCtx& ctx) const -> typename FmtCtx::iterator {
|
||||||
return fmt::format_to(fmt::formatter<double>::format(static_cast<double>(BTG.value) / GIB, ctx), "GiB");
|
// Format as double with GiB suffix, no space
|
||||||
|
return fmt::format_to(ctx.out(), "{:.2f}GiB", static_cast<double>(BTG.value) / GIB);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ namespace {
|
||||||
if (!date.empty() && std::isspace(date.front()))
|
if (!date.empty() && std::isspace(date.front()))
|
||||||
date.erase(date.begin());
|
date.erase(date.begin());
|
||||||
|
|
||||||
// Append appropriate suffix for the date
|
// Append appropriate suffix for the datE
|
||||||
if (date.ends_with("1") && date != "11")
|
if (date.ends_with("1") && date != "11")
|
||||||
date += "st";
|
date += "st";
|
||||||
else if (date.ends_with("2") && date != "12")
|
else if (date.ends_with("2") && date != "12")
|
||||||
|
@ -74,42 +75,47 @@ namespace {
|
||||||
std::string window_manager;
|
std::string window_manager;
|
||||||
std::optional<std::expected<string, NowPlayingError>> now_playing;
|
std::optional<std::expected<string, NowPlayingError>> now_playing;
|
||||||
std::optional<WeatherOutput> weather_info;
|
std::optional<WeatherOutput> weather_info;
|
||||||
|
u64 disk_used;
|
||||||
|
u64 disk_total;
|
||||||
|
std::string shell;
|
||||||
|
|
||||||
static fn fetchSystemData(const Config& config) -> SystemData {
|
static fn fetchSystemData(const Config& config) -> SystemData {
|
||||||
SystemData data;
|
SystemData data;
|
||||||
|
|
||||||
// Group tasks by dependency/type
|
// Single-threaded execution for core system info (faster on Windows)
|
||||||
auto [date, host, kernel] = std::tuple(
|
data.date = GetDate();
|
||||||
std::async(std::launch::async, GetDate),
|
data.host = GetHost();
|
||||||
std::async(std::launch::async, GetHost),
|
data.kernel_version = GetKernelVersion();
|
||||||
std::async(std::launch::async, GetKernelVersion)
|
data.os_version = GetOSVersion();
|
||||||
);
|
data.mem_info = GetMemInfo();
|
||||||
|
|
||||||
auto [osVer, mem, desktop, winManager] = std::tuple(
|
// Desktop environment info (not relevant for Windows)
|
||||||
std::async(std::launch::async, GetOSVersion),
|
data.desktop_environment = std::nullopt;
|
||||||
std::async(std::launch::async, GetMemInfo),
|
data.window_manager = "Windows";
|
||||||
std::async(std::launch::async, GetDesktopEnvironment),
|
|
||||||
std::async(std::launch::async, GetWindowManager)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Conditional async tasks
|
// Parallel execution for disk/shell only
|
||||||
|
auto diskShell = std::async(std::launch::async, [] {
|
||||||
|
auto [used, total] = GetDiskUsage();
|
||||||
|
return std::make_tuple(used, total, GetShell());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Conditional tasks
|
||||||
std::future<WeatherOutput> weather;
|
std::future<WeatherOutput> weather;
|
||||||
std::future<std::expected<string, NowPlayingError>> nowPlaying;
|
std::future<std::expected<string, NowPlayingError>> nowPlaying;
|
||||||
|
|
||||||
if (config.weather.get().enabled)
|
if (config.weather.get().enabled) {
|
||||||
weather = std::async(std::launch::async, [&] { return config.weather.get().getWeatherInfo(); });
|
weather = std::async(std::launch::async, [&config] { return config.weather.get().getWeatherInfo(); });
|
||||||
|
}
|
||||||
|
|
||||||
if (config.now_playing.get().enabled)
|
if (config.now_playing.get().enabled) {
|
||||||
nowPlaying = std::async(std::launch::async, GetNowPlaying);
|
nowPlaying = std::async(std::launch::async, GetNowPlaying);
|
||||||
|
}
|
||||||
|
|
||||||
// Ordered wait for fastest completion
|
// Get remaining results
|
||||||
data.date = date.get();
|
auto [used, total, shell] = diskShell.get();
|
||||||
data.host = host.get();
|
data.disk_used = used;
|
||||||
data.kernel_version = kernel.get();
|
data.disk_total = total;
|
||||||
data.os_version = osVer.get();
|
data.shell = shell;
|
||||||
data.mem_info = mem.get();
|
|
||||||
data.desktop_environment = desktop.get();
|
|
||||||
data.window_manager = winManager.get();
|
|
||||||
|
|
||||||
if (weather.valid())
|
if (weather.valid())
|
||||||
data.weather_info = weather.get();
|
data.weather_info = weather.get();
|
||||||
|
@ -160,25 +166,21 @@ namespace {
|
||||||
|
|
||||||
content.push_back(text(" Hello " + name + "! ") | bold | color(Color::Cyan));
|
content.push_back(text(" Hello " + name + "! ") | bold | color(Color::Cyan));
|
||||||
content.push_back(separator() | color(borderColor));
|
content.push_back(separator() | color(borderColor));
|
||||||
content.push_back(hbox(
|
content.push_back(hbox({
|
||||||
{
|
text(" ") | color(iconColor), // Palette icon
|
||||||
text(" ") | color(iconColor), // Palette icon
|
CreateColorCircles(),
|
||||||
CreateColorCircles(),
|
}));
|
||||||
}
|
|
||||||
));
|
|
||||||
content.push_back(separator() | color(borderColor));
|
content.push_back(separator() | color(borderColor));
|
||||||
|
|
||||||
// Helper function for aligned rows
|
// Helper function for aligned rows
|
||||||
fn createRow = [&](const std::string& icon, const std::string& label, const std::string& value) {
|
fn createRow = [&](const std::string& icon, const std::string& label, const std::string& value) {
|
||||||
return hbox(
|
return hbox({
|
||||||
{
|
text(icon) | color(iconColor),
|
||||||
text(icon) | color(iconColor),
|
text(label) | color(labelColor),
|
||||||
text(label) | color(labelColor),
|
filler(),
|
||||||
filler(),
|
text(value) | color(valueColor),
|
||||||
text(value) | color(valueColor),
|
text(" "),
|
||||||
text(" "),
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// System info rows
|
// System info rows
|
||||||
|
@ -189,39 +191,31 @@ namespace {
|
||||||
const WeatherOutput& weatherInfo = data.weather_info.value();
|
const WeatherOutput& weatherInfo = data.weather_info.value();
|
||||||
|
|
||||||
if (weather.show_town_name)
|
if (weather.show_town_name)
|
||||||
content.push_back(hbox(
|
content.push_back(hbox({
|
||||||
{
|
text(weatherIcon) | color(iconColor),
|
||||||
text(weatherIcon) | color(iconColor),
|
text("Weather") | color(labelColor),
|
||||||
text("Weather") | color(labelColor),
|
filler(),
|
||||||
filler(),
|
|
||||||
|
|
||||||
hbox(
|
hbox({
|
||||||
{
|
text(fmt::format("{}°F ", std::lround(weatherInfo.main.temp))),
|
||||||
text(fmt::format("{}°F ", std::lround(weatherInfo.main.temp))),
|
text("in "),
|
||||||
text("in "),
|
text(weatherInfo.name),
|
||||||
text(weatherInfo.name),
|
text(" "),
|
||||||
text(" "),
|
}) |
|
||||||
}
|
color(valueColor),
|
||||||
) |
|
}));
|
||||||
color(valueColor),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
else
|
else
|
||||||
content.push_back(hbox(
|
content.push_back(hbox({
|
||||||
{
|
text(weatherIcon) | color(iconColor),
|
||||||
text(weatherIcon) | color(iconColor),
|
text("Weather") | color(labelColor),
|
||||||
text("Weather") | color(labelColor),
|
filler(),
|
||||||
filler(),
|
|
||||||
|
|
||||||
hbox(
|
hbox({
|
||||||
{
|
text(fmt::format("{}°F, {}", std::lround(weatherInfo.main.temp), weatherInfo.weather[0].description)),
|
||||||
text(fmt::format("{}°F, {}", std::lround(weatherInfo.main.temp), weatherInfo.weather[0].description)),
|
text(" "),
|
||||||
text(" "),
|
}) |
|
||||||
}
|
color(valueColor),
|
||||||
) |
|
}));
|
||||||
color(valueColor),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content.push_back(separator() | color(borderColor));
|
content.push_back(separator() | color(borderColor));
|
||||||
|
@ -237,11 +231,20 @@ namespace {
|
||||||
else
|
else
|
||||||
ERROR_LOG("Failed to get OS version: {}", data.os_version.error());
|
ERROR_LOG("Failed to get OS version: {}", data.os_version.error());
|
||||||
|
|
||||||
|
// Add disk row after memory info
|
||||||
if (data.mem_info.has_value())
|
if (data.mem_info.has_value())
|
||||||
content.push_back(createRow(memoryIcon, "RAM", fmt::format("{:.2f}", BytesToGiB { *data.mem_info })));
|
content.push_back(createRow(memoryIcon, "RAM", fmt::format("{}", BytesToGiB { *data.mem_info })));
|
||||||
else
|
else
|
||||||
ERROR_LOG("Failed to get memory info: {}", data.mem_info.error());
|
ERROR_LOG("Failed to get memory info: {}", data.mem_info.error());
|
||||||
|
|
||||||
|
// Add Disk usage row
|
||||||
|
content.push_back(
|
||||||
|
createRow(" ", "Disk", fmt::format("{}/{}", BytesToGiB { data.disk_used }, BytesToGiB { data.disk_total }))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add Shell row
|
||||||
|
content.push_back(createRow(" ", "Shell", data.shell));
|
||||||
|
|
||||||
content.push_back(separator() | color(borderColor));
|
content.push_back(separator() | color(borderColor));
|
||||||
|
|
||||||
if (data.desktop_environment.has_value() && *data.desktop_environment != data.window_manager)
|
if (data.desktop_environment.has_value() && *data.desktop_environment != data.window_manager)
|
||||||
|
@ -258,16 +261,14 @@ namespace {
|
||||||
const std::string& npText = *nowPlayingResult;
|
const std::string& npText = *nowPlayingResult;
|
||||||
|
|
||||||
content.push_back(separator() | color(borderColor));
|
content.push_back(separator() | color(borderColor));
|
||||||
content.push_back(hbox(
|
content.push_back(hbox({
|
||||||
{
|
text(musicIcon) | color(iconColor),
|
||||||
text(musicIcon) | color(iconColor),
|
text("Playing") | color(labelColor),
|
||||||
text("Playing") | color(labelColor),
|
text(" "),
|
||||||
text(" "),
|
filler(),
|
||||||
filler(),
|
paragraph(npText) | color(Color::Magenta) | size(WIDTH, LESS_THAN, 30),
|
||||||
paragraph(npText) | color(Color::Magenta) | size(WIDTH, LESS_THAN, 30),
|
text(" "),
|
||||||
text(" "),
|
}));
|
||||||
}
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
const NowPlayingError& error = nowPlayingResult.error();
|
const NowPlayingError& error = nowPlayingResult.error();
|
||||||
|
|
||||||
|
@ -299,10 +300,10 @@ namespace {
|
||||||
|
|
||||||
fn main() -> i32 {
|
fn main() -> i32 {
|
||||||
const Config& config = Config::getInstance();
|
const Config& config = Config::getInstance();
|
||||||
|
SystemData data = SystemData::fetchSystemData(config);
|
||||||
|
|
||||||
SystemData data = SystemData::fetchSystemData(config);
|
// Add vertical box with forced newline
|
||||||
|
Element document = vbox({ hbox({ SystemInfoBox(config, data), filler() }), text("") });
|
||||||
Element document = hbox({ SystemInfoBox(config, data), filler() });
|
|
||||||
|
|
||||||
Screen screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
Screen screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
|
|
@ -51,3 +51,9 @@ fn GetKernelVersion() -> string;
|
||||||
* @brief Get the number of installed packages.
|
* @brief Get the number of installed packages.
|
||||||
*/
|
*/
|
||||||
fn GetPackageCount() -> u64;
|
fn GetPackageCount() -> u64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current disk usage.
|
||||||
|
* @return std::pair<u64, u64> Used space/total space
|
||||||
|
*/
|
||||||
|
fn GetDiskUsage() -> std::pair<u64, u64>;
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
|
|
||||||
#include <iostream>
|
// clang-format off
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <wincrypt.h>
|
#include <wincrypt.h>
|
||||||
#include <winrt/Windows.Foundation.h>
|
|
||||||
#include <winrt/Windows.Media.Control.h>
|
|
||||||
#include <winrt/base.h>
|
|
||||||
#include <winrt/impl/Windows.Media.Control.2.h>
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -17,6 +11,11 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
#include <winrt/Windows.Media.Control.h>
|
||||||
|
#include <winrt/base.h>
|
||||||
|
#include <winrt/impl/Windows.Media.Control.2.h>
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
using RtlGetVersionPtr = NTSTATUS(WINAPI*)(PRTL_OSVERSIONINFOW);
|
using RtlGetVersionPtr = NTSTATUS(WINAPI*)(PRTL_OSVERSIONINFOW);
|
||||||
|
@ -76,15 +75,64 @@ namespace {
|
||||||
return _stricmp(proc.c_str(), name.c_str()) == 0;
|
return _stricmp(proc.c_str(), name.c_str()) == 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn GetParentProcessId(DWORD pid) -> DWORD {
|
||||||
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (hSnapshot == INVALID_HANDLE_VALUE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PROCESSENTRY32 pe32;
|
||||||
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||||
|
DWORD parentPid = 0;
|
||||||
|
|
||||||
|
if (Process32First(hSnapshot, &pe32)) {
|
||||||
|
while (true) {
|
||||||
|
if (pe32.th32ProcessID == pid) {
|
||||||
|
parentPid = pe32.th32ParentProcessID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!Process32Next(hSnapshot, &pe32)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(hSnapshot);
|
||||||
|
return parentPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn GetProcessName(DWORD pid) -> string {
|
||||||
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (hSnapshot == INVALID_HANDLE_VALUE)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
PROCESSENTRY32 pe32;
|
||||||
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||||
|
string processName;
|
||||||
|
|
||||||
|
if (Process32First(hSnapshot, &pe32)) {
|
||||||
|
while (true) {
|
||||||
|
if (pe32.th32ProcessID == pid) {
|
||||||
|
// Explicitly cast array to string to avoid implicit array decay
|
||||||
|
processName = std::string(static_cast<const char*>(pe32.szExeFile));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Process32Next(hSnapshot, &pe32))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(hSnapshot);
|
||||||
|
return processName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn GetMemInfo() -> expected<u64, string> {
|
fn GetMemInfo() -> expected<u64, string> {
|
||||||
u64 mem = 0;
|
MEMORYSTATUSEX memInfo;
|
||||||
|
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
|
||||||
if (!GetPhysicallyInstalledSystemMemory(&mem))
|
if (!GlobalMemoryStatusEx(&memInfo)) {
|
||||||
return std::unexpected("Failed to get physical system memory.");
|
return std::unexpected("Failed to get memory status");
|
||||||
|
}
|
||||||
return mem * 1024;
|
return memInfo.ullTotalPhys;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn GetNowPlaying() -> expected<string, NowPlayingError> {
|
fn GetNowPlaying() -> expected<string, NowPlayingError> {
|
||||||
|
@ -141,7 +189,7 @@ fn GetOSVersion() -> expected<string, string> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::unexpected("Failed to get OS version.");
|
return "Windows";
|
||||||
}
|
}
|
||||||
|
|
||||||
fn GetHost() -> string {
|
fn GetHost() -> string {
|
||||||
|
@ -180,22 +228,20 @@ fn GetWindowManager() -> string {
|
||||||
string windowManager;
|
string windowManager;
|
||||||
|
|
||||||
// Check for third-party WMs
|
// Check for third-party WMs
|
||||||
if (IsProcessRunning(processes, "glazewm.exe")) {
|
if (IsProcessRunning(processes, "glazewm.exe"))
|
||||||
windowManager = "GlazeWM";
|
windowManager = "GlazeWM";
|
||||||
} else if (IsProcessRunning(processes, "fancywm.exe")) {
|
else if (IsProcessRunning(processes, "fancywm.exe"))
|
||||||
windowManager = "FancyWM";
|
windowManager = "FancyWM";
|
||||||
} else if (IsProcessRunning(processes, "komorebi.exe") || IsProcessRunning(processes, "komorebic.exe")) {
|
else if (IsProcessRunning(processes, "komorebi.exe") || IsProcessRunning(processes, "komorebic.exe"))
|
||||||
windowManager = "Komorebi";
|
windowManager = "Komorebi";
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to DWM detection
|
// Fallback to DWM detection
|
||||||
if (windowManager.empty()) {
|
if (windowManager.empty()) {
|
||||||
BOOL compositionEnabled = FALSE;
|
BOOL compositionEnabled = FALSE;
|
||||||
if (SUCCEEDED(DwmIsCompositionEnabled(&compositionEnabled))) {
|
if (SUCCEEDED(DwmIsCompositionEnabled(&compositionEnabled)))
|
||||||
windowManager = compositionEnabled ? "Desktop Window Manager" : "Windows Manager (Basic)";
|
windowManager = compositionEnabled ? "Desktop Window Manager" : "Windows Manager (Basic)";
|
||||||
} else {
|
else
|
||||||
windowManager = "Windows Manager";
|
windowManager = "Windows Manager";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return windowManager;
|
return windowManager;
|
||||||
|
@ -244,4 +290,87 @@ fn GetDesktopEnvironment() -> optional<string> {
|
||||||
} catch (...) { return std::nullopt; }
|
} catch (...) { return std::nullopt; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn GetShell() -> string {
|
||||||
|
// Detect MSYS2/MinGW shells
|
||||||
|
if (getenv("MSYSTEM")) {
|
||||||
|
const char* shell = getenv("SHELL");
|
||||||
|
string shellExe;
|
||||||
|
|
||||||
|
// First try SHELL, then LOGINSHELL
|
||||||
|
if (!shell || strlen(shell) == 0) {
|
||||||
|
shell = getenv("LOGINSHELL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shell) {
|
||||||
|
string shellPath = shell;
|
||||||
|
size_t lastSlash = shellPath.find_last_of("\\/");
|
||||||
|
shellExe = (lastSlash != string::npos) ? shellPath.substr(lastSlash + 1) : shellPath;
|
||||||
|
std::ranges::transform(shellExe, shellExe.begin(), ::tolower);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to process ancestry if both env vars are missing
|
||||||
|
if (shellExe.empty()) {
|
||||||
|
DWORD pid = GetCurrentProcessId();
|
||||||
|
|
||||||
|
while (pid != 0) {
|
||||||
|
string processName = GetProcessName(pid);
|
||||||
|
std::ranges::transform(processName, processName.begin(), [](unsigned char character) {
|
||||||
|
return static_cast<char>(std::tolower(character));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (processName == "bash.exe" || processName == "zsh.exe" || processName == "fish.exe" ||
|
||||||
|
processName == "mintty.exe") {
|
||||||
|
string name = processName.substr(0, processName.find(".exe"));
|
||||||
|
if (!name.empty())
|
||||||
|
name[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(name[0]))); // Capitalize first letter
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
pid = GetParentProcessId(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "MSYS2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shellExe.find("bash") != string::npos)
|
||||||
|
return "Bash";
|
||||||
|
if (shellExe.find("zsh") != string::npos)
|
||||||
|
return "Zsh";
|
||||||
|
if (shellExe.find("fish") != string::npos)
|
||||||
|
return "Fish";
|
||||||
|
return shellExe.empty() ? "MSYS2" : "MSYS2/" + shellExe;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect Windows shells
|
||||||
|
const std::unordered_map<string, string> knownShells = {
|
||||||
|
{ "cmd.exe", "Command Prompt" },
|
||||||
|
{ "powershell.exe", "PowerShell" },
|
||||||
|
{ "pwsh.exe", "PowerShell Core" },
|
||||||
|
{ "windowsterminal.exe", "Windows Terminal" },
|
||||||
|
{ "mintty.exe", "Mintty" },
|
||||||
|
{ "bash.exe", "Windows Subsystem for Linux" }
|
||||||
|
};
|
||||||
|
|
||||||
|
DWORD pid = GetCurrentProcessId();
|
||||||
|
while (pid != 0) {
|
||||||
|
string processName = GetProcessName(pid);
|
||||||
|
std::ranges::transform(processName, processName.begin(), ::tolower);
|
||||||
|
|
||||||
|
if (auto shellIterator = knownShells.find(processName); shellIterator != knownShells.end())
|
||||||
|
return shellIterator->second;
|
||||||
|
|
||||||
|
pid = GetParentProcessId(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Windows Console";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn GetDiskUsage() -> std::pair<u64, u64> {
|
||||||
|
ULARGE_INTEGER freeBytes, totalBytes;
|
||||||
|
|
||||||
|
if (GetDiskFreeSpaceExW(L"C:\\", nullptr, &totalBytes, &freeBytes))
|
||||||
|
return { totalBytes.QuadPart - freeBytes.QuadPart, totalBytes.QuadPart };
|
||||||
|
|
||||||
|
return { 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue