1ms slower on average 💔 sad!

This commit is contained in:
Mars 2025-01-29 02:03:00 -05:00
parent 39a6a5cff0
commit ff3d9bcce8
Signed by: pupbrained
GPG key ID: 0FF5B8826803F895
6 changed files with 166 additions and 88 deletions

View file

@ -9,7 +9,7 @@ AllowShortLoopsOnASingleLine: true
BasedOnStyle: Chromium BasedOnStyle: Chromium
BinPackArguments: false BinPackArguments: false
BinPackParameters: false BinPackParameters: false
ColumnLimit: 100 ColumnLimit: 120
ConstructorInitializerIndentWidth: 2 ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2 ContinuationIndentWidth: 2
Cpp11BracedListStyle: false Cpp11BracedListStyle: false

View file

@ -2,28 +2,27 @@
#include <filesystem> #include <filesystem>
#include <fmt/core.h> #include <fmt/core.h>
#include <stdexcept> #include <stdexcept>
#include <string>
#include "config.h" #include "config.h"
using rfl::Result; using rfl::Result;
namespace fs = std::filesystem; namespace fs = std::filesystem;
inline fn GetConfigPath() -> std::string { inline fn GetConfigPath() -> fs::path {
#ifdef _WIN32 #ifdef _WIN32
const char* localAppData = std::getenv("LOCALAPPDATA"); const char* localAppData = std::getenv("LOCALAPPDATA");
if (!localAppData) if (!localAppData)
throw std::runtime_error("Environment variable LOCALAPPDATA is not set"); throw std::runtime_error("Environment variable LOCALAPPDATA is not set");
return localAppData; return fs::path(localAppData);
#else #else
const char* home = std::getenv("HOME"); const char* home = std::getenv("HOME");
if (!home) if (!home)
throw std::runtime_error("Environment variable HOME is not set"); throw std::runtime_error("Environment variable HOME is not set");
return std::string(home) + "/.config"; return fs::path(home) / ".config";
#endif #endif
} }
@ -34,7 +33,8 @@ fn Config::getInstance() -> Config {
const Result<Config> result = rfl::toml::load<Config>(configPath.string()); const Result<Config> result = rfl::toml::load<Config>(configPath.string());
if (!result) { if (!result) {
fmt::println(stderr, "Failed to load config file: {}", result.error()->what()); ERROR_LOG("Failed to load config file: {}", result.error()->what());
exit(1); exit(1);
} }

View file

@ -1,4 +1,4 @@
#pragma once
#include <rfl.hpp> #include <rfl.hpp>
#include <rfl/Field.hpp> #include <rfl/Field.hpp>
@ -18,7 +18,8 @@ struct NowPlaying {
}; };
struct Weather { struct Weather {
bool enabled = false; bool enabled = false;
bool show_town_name = false;
Location location; Location location;
string api_key; string api_key;

View file

@ -43,11 +43,11 @@ namespace {
date.erase(date.begin()); date.erase(date.begin());
// Append appropriate suffix for the date // Append appropriate suffix for the date
if (date == "1" || date == "21" || date == "31") if (date.ends_with("1") && date != "11")
date += "st"; date += "st";
else if (date == "2" || date == "22") else if (date.ends_with("2") && date != "12")
date += "nd"; date += "nd";
else if (date == "3" || date == "23") else if (date.ends_with("3") && date != "13")
date += "rd"; date += "rd";
else else
date += "th"; date += "th";
@ -59,84 +59,125 @@ namespace {
fn CreateColorCircles() -> Element { fn CreateColorCircles() -> Element {
Elements circles; Elements circles;
for (int i = 0; i < 16; ++i) {
circles.push_back(text("") | bold | color(Color::Palette256(i))); for (int i = 0; i < 16; ++i)
circles.push_back(text(" ")); circles.push_back(hbox({
} text("") | bold | color(Color::Palette256(i)),
text(" "),
}));
return hbox(circles); return hbox(circles);
} }
fn SystemInfoBox(const Config& config) -> Element { fn SystemInfoBox(const Config& config) -> Element {
// Fetch data // Fetch data
const std::string& name = config.general.get().name.get(); const std::string& name = config.general.get().name.get();
std::string date = GetDate(); const std::string& date = GetDate();
const std::string& host = GetHost();
const std::string& kernelVersion = GetKernelVersion();
const std::string& osVersion = GetOSVersion();
u64 memInfo = GetMemInfo(); u64 memInfo = GetMemInfo();
std::string osVersion = GetOSVersion();
Weather weather = config.weather.get(); Weather weather = config.weather.get();
bool nowPlayingEnabled = config.now_playing.get().enabled; bool nowPlayingEnabled = config.now_playing.get().enabled;
std::string nowPlaying = nowPlayingEnabled ? GetNowPlaying() : ""; const std::string& nowPlaying = nowPlayingEnabled ? GetNowPlaying() : "";
// Icon constants (using Nerd Font v3) // Icon constants (using Nerd Font v3)
constexpr const char* calendarIcon = ""; constexpr const char* calendarIcon = "";
constexpr const char* memoryIcon = ""; constexpr const char* hostIcon = " 󰌢 ";
constexpr const char* kernelIcon = "";
constexpr const char* osIcon = ""; constexpr const char* osIcon = "";
constexpr const char* memoryIcon = "";
constexpr const char* weatherIcon = " 󰖐 "; constexpr const char* weatherIcon = " 󰖐 ";
constexpr const char* musicIcon = ""; constexpr const char* musicIcon = "";
const Color::Palette16 labelColor = Color::Yellow; const Color::Palette16 labelColor = Color::Yellow;
const Color::Palette16 valueColor = Color::White; const Color::Palette16 valueColor = Color::White;
const Color::Palette16 borderColor = Color::GrayLight; const Color::Palette16 borderColor = Color::GrayLight;
const Color iconColor = Color::RGB(100, 200, 255); // Bright cyan const Color::Palette16 iconColor = Color::Cyan;
Elements content; Elements content;
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({
text("") | color(iconColor), // Palette icon
CreateColorCircles(),
}));
content.push_back(separator() | color(borderColor));
// Helper function for aligned rows // Helper function for aligned rows
auto createRow = auto createRow = [&](const std::string& icon, const std::string& label, const std::string& value) {
[&](const std::string& emoji, const std::string& label, const std::string& value) { return hbox({
return hbox({ text(emoji), text(icon) | color(iconColor),
text(label) | color(labelColor), text(label) | color(labelColor),
filler(), text(" "),
text(value) | color(valueColor), filler(),
text(" ") }); text(value) | color(valueColor),
}; text(" "),
});
};
// System info rows // System info rows
content.push_back(createRow(calendarIcon, "Date ", date)); content.push_back(createRow(calendarIcon, "Date", date));
content.push_back(createRow(memoryIcon, "RAM ", fmt::format("{:.2f}", BytesToGiB { memInfo })));
content.push_back(createRow(osIcon, "OS ", osVersion));
// Weather row // Weather row
if (weather.enabled) { if (weather.enabled) {
auto weatherInfo = weather.getWeatherInfo(); WeatherOutput weatherInfo = weather.getWeatherInfo();
content.push_back(separator() | color(borderColor));
content.push_back(hbox( if (weather.show_town_name)
{ text(weatherIcon), content.push_back(hbox({
text("Weather ") | color(labelColor), text(weatherIcon) | color(iconColor),
text("Weather") | color(labelColor),
filler(), filler(),
hbox({ text(fmt::format("{}°F ", std::lround(weatherInfo.main.temp))) | color(Color::Red),
text("in "), hbox({
text(weatherInfo.name), text(fmt::format("{}°F ", std::lround(weatherInfo.main.temp))),
text(" ") }) | text("in "),
color(valueColor) } text(weatherInfo.name),
)); text(" "),
}) |
color(valueColor),
}));
else
content.push_back(hbox({
text(weatherIcon) | color(iconColor),
text("Weather") | color(labelColor),
filler(),
hbox({
text(fmt::format("{}°F, {}", std::lround(weatherInfo.main.temp), weatherInfo.weather[0].description)),
text(" "),
}) |
color(valueColor),
}));
} }
content.push_back(separator() | color(borderColor));
if (!host.empty())
content.push_back(createRow(hostIcon, "Host", host));
if (!kernelVersion.empty())
content.push_back(createRow(kernelIcon, "Kernel", kernelVersion));
if (!osVersion.empty())
content.push_back(createRow(osIcon, "OS", osVersion));
if (memInfo > 0)
content.push_back(createRow(memoryIcon, "RAM", fmt::format("{:.2f}", BytesToGiB { memInfo })));
// Now Playing row // Now Playing row
if (nowPlayingEnabled && !nowPlaying.empty()) { if (nowPlayingEnabled && !nowPlaying.empty()) {
content.push_back(separator() | color(borderColor)); content.push_back(separator() | color(borderColor));
content.push_back(hbox({ text(musicIcon), content.push_back(hbox({
text("Now Playing ") | color(labelColor), text(musicIcon) | color(iconColor),
filler(), text("Music") | color(labelColor),
text(nowPlaying), text(" "),
text(" ") | color(Color::Magenta) })); filler(),
text(nowPlaying.length() > 30 ? nowPlaying.substr(0, 30) + "..." : nowPlaying) | color(Color::Magenta),
text(" "),
}));
} }
// Color circles section
content.push_back(filler());
content.push_back(separator() | color(borderColor));
content.push_back(hbox({ text("") | color(iconColor), // Palette icon
CreateColorCircles() }));
return vbox(content) | borderRounded | color(Color::White); return vbox(content) | borderRounded | color(Color::White);
} }
} }

View file

@ -1,32 +1,39 @@
#ifdef __linux__ #ifdef __linux__
#include <cstring> #include <cstring>
#include <filesystem>
#include <fmt/format.h> #include <fmt/format.h>
#include <fstream> #include <fstream>
#include <sdbus-c++/sdbus-c++.h> #include <sdbus-c++/sdbus-c++.h>
#include <sys/utsname.h>
#include <vector> #include <vector>
#include "os.h" #include "os.h"
#include "src/util/macros.h"
enum SessionType : u8 { Wayland, X11, TTY, Unknown }; enum SessionType : u8 { Wayland, X11, TTY, Unknown };
fn ParseLineAsNumber(const std::string& input) -> u64 { fn ParseLineAsNumber(const std::string& input) -> u64 {
usize start = input.find_first_of("0123456789"); usize start = input.find_first_of("0123456789");
if (start == std::string::npos) if (start == std::string::npos) {
throw std::runtime_error("No number found in input"); ERROR_LOG("No number found in input");
return 0;
}
usize end = input.find_first_not_of("0123456789", start); usize end = input.find_first_not_of("0123456789", start);
return std::stoull(input.substr(start, end - start)); return std::stoull(input.substr(start, end - start));
} }
fn MeminfoParse(const std::filesystem::path& filepath) -> u64 { fn MeminfoParse() -> u64 {
std::ifstream input(filepath); constexpr const char* path = "/proc/meminfo";
if (!input.is_open()) std::ifstream input(path);
throw std::runtime_error("Failed to open " + filepath.string());
if (!input.is_open()) {
ERROR_LOG("Failed to open {}", path);
return 0;
}
std::string line; std::string line;
@ -34,16 +41,21 @@ fn MeminfoParse(const std::filesystem::path& filepath) -> u64 {
if (line.starts_with("MemTotal")) if (line.starts_with("MemTotal"))
return ParseLineAsNumber(line); return ParseLineAsNumber(line);
throw std::runtime_error("MemTotal line not found in " + filepath.string()); ERROR_LOG("MemTotal line not found in {}", path);
return 0;
} }
fn GetMemInfo() -> u64 { return MeminfoParse("/proc/meminfo") * 1024; } fn GetMemInfo() -> u64 { return MeminfoParse() * 1024; }
fn GetOSVersion() -> std::string { fn GetOSVersion() -> std::string {
std::ifstream file("/etc/os-release"); constexpr const char* path = "/etc/os-release";
if (!file.is_open()) std::ifstream file(path);
throw std::runtime_error("Failed to open /etc/os-release");
if (!file.is_open()) {
ERROR_LOG("Failed to open {}", path);
return "";
}
string line; string line;
const string prefix = "PRETTY_NAME="; const string prefix = "PRETTY_NAME=";
@ -58,7 +70,8 @@ fn GetOSVersion() -> std::string {
return prettyName; return prettyName;
} }
throw std::runtime_error("PRETTY_NAME line not found in /etc/os-release"); ERROR_LOG("PRETTY_NAME line not found in {}", path);
return "";
} }
fn GetMprisPlayers(sdbus::IConnection& connection) -> std::vector<string> { fn GetMprisPlayers(sdbus::IConnection& connection) -> std::vector<string> {
@ -66,8 +79,7 @@ fn GetMprisPlayers(sdbus::IConnection& connection) -> std::vector<string> {
const sdbus::ObjectPath dbusObjectPath = sdbus::ObjectPath("/org/freedesktop/DBus"); const sdbus::ObjectPath dbusObjectPath = sdbus::ObjectPath("/org/freedesktop/DBus");
const char* dbusMethodListNames = "ListNames"; const char* dbusMethodListNames = "ListNames";
const std::unique_ptr<sdbus::IProxy> dbusProxy = const std::unique_ptr<sdbus::IProxy> dbusProxy = createProxy(connection, dbusInterface, dbusObjectPath);
createProxy(connection, dbusInterface, dbusObjectPath);
std::vector<string> names; std::vector<string> names;
@ -76,8 +88,7 @@ fn GetMprisPlayers(sdbus::IConnection& connection) -> std::vector<string> {
std::vector<string> mprisPlayers; std::vector<string> mprisPlayers;
for (const std::basic_string<char>& name : names) for (const std::basic_string<char>& name : names)
if (const char* mprisInterfaceName = "org.mpris.MediaPlayer2"; if (const char* mprisInterfaceName = "org.mpris.MediaPlayer2"; name.find(mprisInterfaceName) != std::string::npos)
name.find(mprisInterfaceName) != std::string::npos)
mprisPlayers.push_back(name); mprisPlayers.push_back(name);
return mprisPlayers; return mprisPlayers;
@ -92,30 +103,32 @@ fn GetActivePlayer(const std::vector<string>& mprisPlayers) -> string {
fn GetNowPlaying() -> string { fn GetNowPlaying() -> string {
try { try {
const char *playerObjectPath = "/org/mpris/MediaPlayer2", const char *playerObjectPath = "/org/mpris/MediaPlayer2", *playerInterfaceName = "org.mpris.MediaPlayer2.Player";
*playerInterfaceName = "org.mpris.MediaPlayer2.Player";
std::unique_ptr<sdbus::IConnection> connection = sdbus::createSessionBusConnection(); std::unique_ptr<sdbus::IConnection> connection = sdbus::createSessionBusConnection();
std::vector<string> mprisPlayers = GetMprisPlayers(*connection); std::vector<string> mprisPlayers = GetMprisPlayers(*connection);
if (mprisPlayers.empty()) if (mprisPlayers.empty()) {
DEBUG_LOG("No MPRIS players found");
return ""; return "";
}
string activePlayer = GetActivePlayer(mprisPlayers); string activePlayer = GetActivePlayer(mprisPlayers);
if (activePlayer.empty()) if (activePlayer.empty()) {
DEBUG_LOG("No active player found");
return ""; return "";
}
auto playerProxy = sdbus::createProxy( std::unique_ptr<sdbus::IProxy> playerProxy =
*connection, sdbus::ServiceName(activePlayer), sdbus::ObjectPath(playerObjectPath) sdbus::createProxy(*connection, sdbus::ServiceName(activePlayer), sdbus::ObjectPath(playerObjectPath));
);
sdbus::Variant metadataVariant = sdbus::Variant metadataVariant = playerProxy->getProperty("Metadata").onInterface(playerInterfaceName);
playerProxy->getProperty("Metadata").onInterface(playerInterfaceName);
if (metadataVariant.containsValueOfType<std::map<std::string, sdbus::Variant>>()) { if (metadataVariant.containsValueOfType<std::map<std::string, sdbus::Variant>>()) {
const auto& metadata = metadataVariant.get<std::map<std::string, sdbus::Variant>>(); const std::map<std::basic_string<char>, sdbus::Variant>& metadata =
metadataVariant.get<std::map<std::string, sdbus::Variant>>();
auto iter = metadata.find("xesam:title"); auto iter = metadata.find("xesam:title");
@ -123,8 +136,10 @@ fn GetNowPlaying() -> string {
return iter->second.get<std::string>(); return iter->second.get<std::string>();
} }
} catch (const sdbus::Error& e) { } catch (const sdbus::Error& e) {
if (e.getName() != "com.github.altdesktop.playerctld.NoActivePlayer") if (e.getName() != "com.github.altdesktop.playerctld.NoActivePlayer") {
return fmt::format("Error: {}", e.what()); ERROR_LOG("Error: {}", e.what());
return "";
}
return "No active player"; return "No active player";
} }
@ -138,17 +153,33 @@ fn GetShell() -> string {
return shell ? shell : ""; return shell ? shell : "";
} }
fn GetProductFamily() -> string { fn GetHost() -> string {
std::ifstream file("/sys/class/dmi/id/product_family"); constexpr const char* path = "/sys/class/dmi/id/product_family";
if (!file.is_open()) std::ifstream file(path);
throw std::runtime_error("Failed to open /sys/class/dmi/id/product_family"); if (!file.is_open()) {
ERROR_LOG("Failed to open {}", path);
return "";
}
std::string productFamily; std::string productFamily;
if (!std::getline(file, productFamily)) {
std::getline(file, productFamily); ERROR_LOG("Failed to read from {}", path);
return "";
}
return productFamily; return productFamily;
} }
fn GetKernelVersion() -> string {
struct utsname uts;
if (uname(&uts) == -1) {
ERROR_LOG("uname() failed: {}", std::strerror(errno));
return "";
}
return static_cast<const char*>(uts.release);
}
#endif #endif

View file

@ -36,4 +36,9 @@ fn GetShell() -> string;
/** /**
* @brief Get the product family * @brief Get the product family
*/ */
fn GetProductFamily() -> string; fn GetHost() -> string;
/**
* @brief Get the kernel version.
*/
fn GetKernelVersion() -> string;