i think this is better
This commit is contained in:
parent
8cbc00372d
commit
ea6bf62c90
23
flake.nix
23
flake.nix
|
@ -18,10 +18,13 @@
|
|||
system: let
|
||||
pkgs = import nixpkgs {inherit system;};
|
||||
|
||||
stdenv =
|
||||
if pkgs.hostPlatform.isLinux
|
||||
then pkgs.stdenvAdapters.useMoldLinker pkgs.llvmPackages_19.stdenv
|
||||
else pkgs.llvmPackages_19.stdenv;
|
||||
stdenv = with pkgs;
|
||||
(
|
||||
if hostPlatform.isLinux
|
||||
then stdenvAdapters.useMoldLinker
|
||||
else lib.id
|
||||
)
|
||||
llvmPackages_19.stdenv;
|
||||
|
||||
sources = import ./_sources/generated.nix {
|
||||
inherit (pkgs) fetchFromGitHub fetchgit fetchurl dockerTools;
|
||||
|
@ -71,17 +74,17 @@
|
|||
++ linuxPkgs
|
||||
++ darwinPkgs;
|
||||
|
||||
linuxPkgs =
|
||||
nixpkgs.lib.optionals stdenv.isLinux (with pkgs; [
|
||||
linuxPkgs = nixpkgs.lib.optionals stdenv.isLinux (with pkgs;
|
||||
[
|
||||
pkgsStatic.glib
|
||||
systemdLibs
|
||||
sdbus-cpp
|
||||
valgrind
|
||||
xorg.libX11
|
||||
])
|
||||
++ (with pkgs.pkgsStatic; [
|
||||
]
|
||||
++ (with pkgsStatic; [
|
||||
wayland
|
||||
]);
|
||||
]));
|
||||
|
||||
darwinPkgs = nixpkgs.lib.optionals stdenv.isDarwin (with pkgs.pkgsStatic.darwin.apple_sdk.frameworks; [
|
||||
Foundation
|
||||
|
@ -156,7 +159,7 @@
|
|||
]
|
||||
++ deps;
|
||||
|
||||
LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath deps}";
|
||||
LD_LIBRARY_PATH = "${lib.makeLibraryPath deps}";
|
||||
|
||||
name = "C++";
|
||||
};
|
||||
|
|
|
@ -48,6 +48,7 @@ common_cpp_args = [
|
|||
'-Wno-switch-default',
|
||||
'-Wunused-function',
|
||||
'-fvisibility=hidden',
|
||||
'-fno-strict-enums',
|
||||
]
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
|
|
144
src/main.cpp
144
src/main.cpp
|
@ -5,6 +5,7 @@
|
|||
#include <fmt/format.h>
|
||||
#include <ftxui/dom/elements.hpp>
|
||||
#include <ftxui/screen/screen.hpp>
|
||||
#include <future>
|
||||
#include <string>
|
||||
|
||||
#include "config/config.h"
|
||||
|
@ -23,11 +24,13 @@ constexpr u64 GIB = 1'073'741'824;
|
|||
template <>
|
||||
struct fmt::formatter<BytesToGiB> : fmt::formatter<double> {
|
||||
template <typename FmtCtx>
|
||||
constexpr auto format(const BytesToGiB& BTG, FmtCtx& ctx) const -> typename FmtCtx::iterator {
|
||||
auto out = fmt::formatter<double>::format(static_cast<double>(BTG.value) / GIB, ctx);
|
||||
*out++ = 'G';
|
||||
*out++ = 'i';
|
||||
*out++ = 'B';
|
||||
constexpr fn format(const BytesToGiB& BTG, FmtCtx& ctx) const -> typename FmtCtx::iterator {
|
||||
typename FmtCtx::iterator out = fmt::formatter<double>::format(static_cast<double>(BTG.value) / GIB, ctx);
|
||||
|
||||
*out++ = 'G';
|
||||
*out++ = 'i';
|
||||
*out++ = 'B';
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
@ -35,8 +38,16 @@ struct fmt::formatter<BytesToGiB> : fmt::formatter<double> {
|
|||
namespace {
|
||||
fn GetDate() -> std::string {
|
||||
// Get current local time
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::tm localTime = *std::localtime(&now);
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::tm localTime;
|
||||
|
||||
#ifdef __WIN32__
|
||||
if (localtime_s(&localTime, &now) != 0)
|
||||
ERROR_LOG("localtime_s failed");
|
||||
#else
|
||||
if (localtime_r(&now, &localTime) == nullptr)
|
||||
ERROR_LOG("localtime_r failed");
|
||||
#endif
|
||||
|
||||
// Format the date using fmt::format
|
||||
std::string date = fmt::format("{:%e}", localTime);
|
||||
|
@ -58,6 +69,63 @@ namespace {
|
|||
return fmt::format("{:%B} {}", localTime, date);
|
||||
}
|
||||
|
||||
struct SystemData {
|
||||
std::string date;
|
||||
std::string host;
|
||||
std::string kernel_version;
|
||||
std::string os_version;
|
||||
std::expected<u64, std::string> mem_info;
|
||||
std::string desktop_environment;
|
||||
std::string window_manager;
|
||||
std::optional<std::string> now_playing;
|
||||
std::optional<WeatherOutput> weather_info;
|
||||
|
||||
static fn fetchSystemData(const Config& config) -> SystemData {
|
||||
SystemData data;
|
||||
|
||||
std::launch launchPolicy = std::launch::async | std::launch::deferred;
|
||||
|
||||
if (std::thread::hardware_concurrency() >= 8)
|
||||
launchPolicy = std::launch::async;
|
||||
|
||||
// Launch async tasks
|
||||
std::future<string> futureDate = std::async(launchPolicy, GetDate);
|
||||
std::future<string> futureHost = std::async(launchPolicy, GetHost);
|
||||
std::future<string> futureKernel = std::async(launchPolicy, GetKernelVersion);
|
||||
std::future<string> futureOs = std::async(launchPolicy, GetOSVersion);
|
||||
std::future<std::expected<u64, string>> futureMem = std::async(launchPolicy, GetMemInfo);
|
||||
std::future<string> futureDe = std::async(launchPolicy, GetDesktopEnvironment);
|
||||
std::future<string> futureWm = std::async(launchPolicy, GetWindowManager);
|
||||
|
||||
std::future<WeatherOutput> futureWeather;
|
||||
|
||||
if (config.weather.get().enabled)
|
||||
futureWeather = std::async(std::launch::async, [&config]() { return config.weather.get().getWeatherInfo(); });
|
||||
|
||||
std::future<std::string> futureNowPlaying;
|
||||
|
||||
if (config.now_playing.get().enabled)
|
||||
futureNowPlaying = std::async(std::launch::async, GetNowPlaying);
|
||||
|
||||
// Collect results
|
||||
data.date = futureDate.get();
|
||||
data.host = futureHost.get();
|
||||
data.kernel_version = futureKernel.get();
|
||||
data.os_version = futureOs.get();
|
||||
data.mem_info = futureMem.get();
|
||||
data.desktop_environment = futureDe.get();
|
||||
data.window_manager = futureWm.get();
|
||||
|
||||
if (config.weather.get().enabled)
|
||||
data.weather_info = futureWeather.get();
|
||||
|
||||
if (config.now_playing.get().enabled)
|
||||
data.now_playing = futureNowPlaying.get();
|
||||
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
using namespace ftxui;
|
||||
|
||||
fn CreateColorCircles() -> Element {
|
||||
|
@ -72,19 +140,11 @@ namespace {
|
|||
return hbox(circles);
|
||||
}
|
||||
|
||||
fn SystemInfoBox(const Config& config) -> Element {
|
||||
fn SystemInfoBox(const Config& config, const SystemData& data) -> Element {
|
||||
// Fetch data
|
||||
const string& name = config.general.get().name.get();
|
||||
const string& date = GetDate();
|
||||
const Weather weather = config.weather.get();
|
||||
const string& host = GetHost();
|
||||
const string& kernelVersion = GetKernelVersion();
|
||||
const string& osVersion = GetOSVersion();
|
||||
const u64 memInfo = GetMemInfo().value_or(0);
|
||||
const string& desktopEnvironment = GetDesktopEnvironment();
|
||||
const string& windowManager = GetWindowManager();
|
||||
const bool nowPlayingEnabled = config.now_playing.get().enabled;
|
||||
const string& nowPlaying = nowPlayingEnabled ? GetNowPlaying() : "";
|
||||
const string& name = config.general.get().name.get();
|
||||
const Weather weather = config.weather.get();
|
||||
const bool nowPlayingEnabled = config.now_playing.get().enabled;
|
||||
|
||||
const char *calendarIcon = "", *hostIcon = "", *kernelIcon = "", *osIcon = "", *memoryIcon = "", *weatherIcon = "",
|
||||
*musicIcon = "";
|
||||
|
@ -115,7 +175,7 @@ namespace {
|
|||
content.push_back(separator() | color(borderColor));
|
||||
|
||||
// Helper function for aligned rows
|
||||
auto 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({
|
||||
text(icon) | color(iconColor),
|
||||
text(label) | color(labelColor),
|
||||
|
@ -126,11 +186,11 @@ namespace {
|
|||
};
|
||||
|
||||
// System info rows
|
||||
content.push_back(createRow(calendarIcon, "Date", date));
|
||||
content.push_back(createRow(calendarIcon, "Date", data.date));
|
||||
|
||||
// Weather row
|
||||
if (weather.enabled) {
|
||||
WeatherOutput weatherInfo = weather.getWeatherInfo();
|
||||
if (weather.enabled && data.weather_info.has_value()) {
|
||||
const WeatherOutput& weatherInfo = data.weather_info.value();
|
||||
|
||||
if (weather.show_town_name)
|
||||
content.push_back(hbox({
|
||||
|
@ -162,35 +222,41 @@ namespace {
|
|||
|
||||
content.push_back(separator() | color(borderColor));
|
||||
|
||||
if (!host.empty())
|
||||
content.push_back(createRow(hostIcon, "Host", host));
|
||||
if (!data.host.empty())
|
||||
content.push_back(createRow(hostIcon, "Host", data.host));
|
||||
|
||||
if (!kernelVersion.empty())
|
||||
content.push_back(createRow(kernelIcon, "Kernel", kernelVersion));
|
||||
if (!data.kernel_version.empty())
|
||||
content.push_back(createRow(kernelIcon, "Kernel", data.kernel_version));
|
||||
|
||||
if (!osVersion.empty())
|
||||
content.push_back(createRow(osIcon, "OS", osVersion));
|
||||
if (!data.os_version.empty())
|
||||
content.push_back(createRow(osIcon, "OS", data.os_version));
|
||||
|
||||
if (memInfo > 0)
|
||||
content.push_back(createRow(memoryIcon, "RAM", fmt::format("{:.2f}", BytesToGiB { memInfo })));
|
||||
if (data.mem_info.has_value())
|
||||
content.push_back(createRow(memoryIcon, "RAM", fmt::format("{:.2f}", BytesToGiB { data.mem_info.value() })));
|
||||
else
|
||||
ERROR_LOG("Failed to get memory info: {}", data.mem_info.error());
|
||||
|
||||
content.push_back(separator() | color(borderColor));
|
||||
|
||||
if (!desktopEnvironment.empty() && desktopEnvironment != windowManager)
|
||||
content.push_back(createRow(" ", "DE", desktopEnvironment));
|
||||
if (!data.desktop_environment.empty() && data.desktop_environment != data.window_manager)
|
||||
content.push_back(createRow(" ", "DE", data.desktop_environment));
|
||||
|
||||
if (!windowManager.empty())
|
||||
content.push_back(createRow(" ", "WM", windowManager));
|
||||
if (!data.window_manager.empty())
|
||||
content.push_back(createRow(" ", "WM", data.window_manager));
|
||||
|
||||
// Now Playing row
|
||||
if (nowPlayingEnabled && !nowPlaying.empty()) {
|
||||
if (nowPlayingEnabled && data.now_playing.has_value()) {
|
||||
content.push_back(separator() | color(borderColor));
|
||||
content.push_back(hbox({
|
||||
text(musicIcon) | color(iconColor),
|
||||
text("Music") | color(labelColor),
|
||||
text(" "),
|
||||
filler(),
|
||||
text(nowPlaying.length() > 30 ? nowPlaying.substr(0, 30) + "..." : nowPlaying) | color(Color::Magenta),
|
||||
text(
|
||||
data.now_playing.value().length() > 30 ? data.now_playing.value().substr(0, 30) + "..."
|
||||
: data.now_playing.value()
|
||||
) |
|
||||
color(Color::Magenta),
|
||||
text(" "),
|
||||
}));
|
||||
}
|
||||
|
@ -202,7 +268,9 @@ namespace {
|
|||
fn main() -> i32 {
|
||||
const Config& config = Config::getInstance();
|
||||
|
||||
Element document = hbox({ SystemInfoBox(config), filler() });
|
||||
SystemData data = SystemData::fetchSystemData(config);
|
||||
|
||||
Element document = hbox({ SystemInfoBox(config, data), filler() });
|
||||
|
||||
Screen screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||
Render(screen, document);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
#ifdef __APPLE__
|
||||
|
||||
#include <expected>
|
||||
#include <map>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "macos/bridge.h"
|
||||
#include "os.h"
|
||||
|
||||
fn GetMemInfo() -> u64 {
|
||||
fn GetMemInfo() -> std::expected<u64, string> {
|
||||
u64 mem = 0;
|
||||
usize size = sizeof(mem);
|
||||
|
||||
sysctlbyname("hw.memsize", &mem, &size, nullptr, 0);
|
||||
if (sysctlbyname("hw.memsize", &mem, &size, nullptr, 0) == -1)
|
||||
return std::unexpected(std::string("sysctlbyname failed: ") + strerror(errno));
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
@ -27,9 +28,11 @@ fn GetOSVersion() -> string { return GetMacOSVersion(); }
|
|||
|
||||
fn GetDesktopEnvironment() -> string { return "Aqua"; }
|
||||
|
||||
fn GetWindowManager() -> string { return "Yabai"; }
|
||||
|
||||
fn GetKernelVersion() -> string {
|
||||
std::array<char, 256> kernelVersion;
|
||||
size_t kernelVersionLen = sizeof(kernelVersion);
|
||||
usize kernelVersionLen = sizeof(kernelVersion);
|
||||
|
||||
sysctlbyname("kern.osrelease", kernelVersion.data(), &kernelVersionLen, nullptr, 0);
|
||||
|
||||
|
@ -42,7 +45,7 @@ fn GetHost() -> string {
|
|||
|
||||
sysctlbyname("hw.model", hwModel.data(), &hwModelLen, nullptr, 0);
|
||||
|
||||
// shamelessly stolen from https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/host/host_mac.c
|
||||
// taken from https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/host/host_mac.c
|
||||
// shortened a lot of the entries to remove unnecessary info
|
||||
std::map<std::string, std::string> modelNameByHwModel = {
|
||||
// MacBook Pro
|
||||
|
|
|
@ -5,20 +5,19 @@
|
|||
|
||||
#import "bridge.h"
|
||||
|
||||
#include "../../util/macros.h"
|
||||
|
||||
using MRMediaRemoteGetNowPlayingInfoFunction =
|
||||
void (*)(dispatch_queue_t queue, void (^handler)(NSDictionary* information));
|
||||
|
||||
@implementation Bridge
|
||||
+ (NSDictionary*)currentPlayingMetadata {
|
||||
CFURLRef ref = CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
CFSTR("/System/Library/PrivateFrameworks/MediaRemote.framework"),
|
||||
kCFURLPOSIXPathStyle,
|
||||
false
|
||||
kCFAllocatorDefault, CFSTR("/System/Library/PrivateFrameworks/MediaRemote.framework"), kCFURLPOSIXPathStyle, false
|
||||
);
|
||||
|
||||
if (!ref) {
|
||||
NSLog(@"Failed to load MediaRemote framework");
|
||||
ERROR_LOG("Failed to load MediaRemote framework");
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -26,17 +25,16 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
|
|||
CFRelease(ref);
|
||||
|
||||
if (!bundle) {
|
||||
NSLog(@"Failed to load MediaRemote framework");
|
||||
ERROR_LOG("Failed to load MediaRemote framework");
|
||||
return nil;
|
||||
}
|
||||
|
||||
MRMediaRemoteGetNowPlayingInfoFunction mrMediaRemoteGetNowPlayingInfo =
|
||||
reinterpret_cast<MRMediaRemoteGetNowPlayingInfoFunction>(
|
||||
CFBundleGetFunctionPointerForName(bundle, CFSTR("MRMediaRemoteGetNowPlayingInfo"))
|
||||
);
|
||||
auto mrMediaRemoteGetNowPlayingInfo = std::bit_cast<MRMediaRemoteGetNowPlayingInfoFunction>(
|
||||
CFBundleGetFunctionPointerForName(bundle, CFSTR("MRMediaRemoteGetNowPlayingInfo"))
|
||||
);
|
||||
|
||||
if (!mrMediaRemoteGetNowPlayingInfo) {
|
||||
NSLog(@"Failed to get function pointer for MRMediaRemoteGetNowPlayingInfo");
|
||||
ERROR_LOG("Failed to get function pointer for MRMediaRemoteGetNowPlayingInfo");
|
||||
CFRelease(bundle);
|
||||
return nil;
|
||||
}
|
||||
|
@ -55,6 +53,7 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
|
|||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
CFRelease(bundle);
|
||||
|
||||
return nowPlayingInfo;
|
||||
}
|
||||
|
||||
|
@ -63,15 +62,12 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
|
|||
|
||||
NSOperatingSystemVersion osVersion = [processInfo operatingSystemVersion];
|
||||
|
||||
NSString* version;
|
||||
NSString* version = nullptr;
|
||||
if (osVersion.patchVersion == 0) {
|
||||
version =
|
||||
[NSString stringWithFormat:@"%ld.%ld", osVersion.majorVersion, osVersion.minorVersion];
|
||||
version = [NSString stringWithFormat:@"%ld.%ld", osVersion.majorVersion, osVersion.minorVersion];
|
||||
} else {
|
||||
version = [NSString stringWithFormat:@"%ld.%ld.%ld",
|
||||
osVersion.majorVersion,
|
||||
osVersion.minorVersion,
|
||||
osVersion.patchVersion];
|
||||
version = [NSString
|
||||
stringWithFormat:@"%ld.%ld.%ld", osVersion.majorVersion, osVersion.minorVersion, osVersion.patchVersion];
|
||||
}
|
||||
|
||||
// Dictionary to map macOS versions to their respective names
|
||||
|
|
Loading…
Reference in a new issue