This commit is contained in:
Mars 2025-05-09 23:37:04 -04:00
parent 5872ee26a6
commit bbf32bd0f2
5 changed files with 54 additions and 87 deletions

View file

@ -2117,7 +2117,7 @@ namespace argparse {
}; };
fn consume_digits = [=](StringView sd) -> StringView { fn consume_digits = [=](StringView sd) -> StringView {
const char* const it = std::ranges::find_if_not(sd, is_digit); const auto it = std::ranges::find_if_not(sd, is_digit);
return sd.substr(static_cast<usize>(it - std::begin(sd))); return sd.substr(static_cast<usize>(it - std::begin(sd)));
}; };

View file

@ -1762,13 +1762,9 @@ namespace matchit {
template <typename T> template <typename T>
constexpr fn asDsVia = [](auto... members) { return [members...](auto... pats) { return as<T>(and_(app(members, pats)...)); }; }; constexpr fn asDsVia = [](auto... members) { return [members...](auto... pats) { return as<T>(and_(app(members, pats)...)); }; };
constexpr fn within = [](const auto& first, const auto& last) { constexpr fn in = [](const auto& first, const auto& last) {
return meet([=](auto&& v) { return first <= v && v <= last; }); return meet([=](auto&& v) { return first <= v && v <= last; });
}; };
constexpr fn between = [](const auto& first, const auto& last) {
return meet([=](auto&& v) { return first < v && v < last; });
};
} // namespace impl } // namespace impl
using impl::_; using impl::_;
@ -1780,6 +1776,7 @@ namespace matchit {
using impl::dsVia; using impl::dsVia;
using impl::expr; using impl::expr;
using impl::Id; using impl::Id;
using impl::in;
using impl::is; using impl::is;
using impl::match; using impl::match;
using impl::matched; using impl::matched;
@ -1792,6 +1789,5 @@ namespace matchit {
using impl::Subrange; using impl::Subrange;
using impl::SubrangeT; using impl::SubrangeT;
using impl::when; using impl::when;
using impl::within;
} // namespace matchit } // namespace matchit
// NOLINTEND(readability-identifier-*, cppcoreguidelines-special-member-functions) // NOLINTEND(readability-identifier-*, cppcoreguidelines-special-member-functions)

View file

@ -53,15 +53,15 @@ location = "London" # Your city name
#ifdef _WIN32 #ifdef _WIN32
if (Result<String> result = GetEnv("LOCALAPPDATA")) if (Result<String> result = GetEnv("LOCALAPPDATA"))
possiblePaths.push_back(fs::path(*result) / "draconis++" / "config.toml"); possiblePaths.emplace_back(fs::path(*result) / "draconis++" / "config.toml");
if (Result<String> result = GetEnv("USERPROFILE")) { if (Result<String> result = GetEnv("USERPROFILE")) {
possiblePaths.push_back(fs::path(*result) / ".config" / "draconis++" / "config.toml"); possiblePaths.emplace_back(fs::path(*result) / ".config" / "draconis++" / "config.toml");
possiblePaths.push_back(fs::path(*result) / "AppData" / "Local" / "draconis++" / "config.toml"); possiblePaths.emplace_back(fs::path(*result) / "AppData" / "Local" / "draconis++" / "config.toml");
} }
if (Result<String> result = GetEnv("APPDATA")) if (Result<String> result = GetEnv("APPDATA"))
possiblePaths.push_back(fs::path(*result) / "draconis++" / "config.toml"); possiblePaths.emplace_back(fs::path(*result) / "draconis++" / "config.toml");
#else #else
if (Result<String> result = GetEnv("XDG_CONFIG_HOME")) if (Result<String> result = GetEnv("XDG_CONFIG_HOME"))
possiblePaths.emplace_back(fs::path(*result) / "draconis++" / "config.toml"); possiblePaths.emplace_back(fs::path(*result) / "draconis++" / "config.toml");
@ -72,7 +72,7 @@ location = "London" # Your city name
} }
#endif #endif
possiblePaths.push_back(fs::path(".") / "config.toml"); possiblePaths.emplace_back(fs::path(".") / "config.toml");
for (const fs::path& path : possiblePaths) for (const fs::path& path : possiblePaths)
if (std::error_code errc; fs::exists(path, errc) && !errc) if (std::error_code errc; fs::exists(path, errc) && !errc)
@ -104,31 +104,6 @@ location = "London" # Your city name
return false; return false;
} }
String defaultName;
#ifdef _WIN32
Array<char, 256> username;
DWORD size = sizeof(username);
if (GetUserNameA(username.data(), &size)) {
defaultName = username.data();
} else {
debug_log("Failed to get username: {}", GetLastError());
defaultName = "User";
}
#else
const passwd* pwd = getpwuid(getuid());
CStr pwdName = pwd ? pwd->pw_name : nullptr;
const Result<String> envUser = util::helpers::GetEnv("USER");
const Result<String> envLogname = util::helpers::GetEnv("LOGNAME");
defaultName = pwdName ? pwdName : envUser ? *envUser
: envLogname ? *envLogname
: "User";
#endif
std::ofstream file(configPath); std::ofstream file(configPath);
if (!file) { if (!file) {
error_log("Failed to open config file for writing: {}", configPath.string()); error_log("Failed to open config file for writing: {}", configPath.string());
@ -136,19 +111,15 @@ location = "London" # Your city name
} }
try { try {
const String formattedConfig = std::format(defaultConfigTemplate, defaultName); const String defaultName = General::getDefaultName();
const String formattedConfig = std::vformat(defaultConfigTemplate, std::make_format_args(defaultName));
file << formattedConfig; file << formattedConfig;
} catch (const std::format_error& fmtErr) { } catch (const std::format_error& fmtErr) {
error_log("Failed to format default config string: {}. Using fallback name 'User'.", fmtErr.what()); error_log("Failed to format default config string: {}", fmtErr.what());
try {
const String fallbackConfig = std::format(defaultConfigTemplate, "User");
file << fallbackConfig;
} catch (...) {
error_log("Failed to format default config even with fallback name.");
return false; return false;
} }
}
if (!file) { if (!file) {
error_log("Failed to write to config file: {}", configPath.string()); error_log("Failed to write to config file: {}", configPath.string());
@ -189,9 +160,7 @@ fn Config::getInstance() -> Config {
const bool exists = fs::exists(configPath, errc); const bool exists = fs::exists(configPath, errc);
if (errc) if (errc)
warn_log( warn_log("Failed to check if config file exists at {}: {}. Assuming it doesn't.", configPath.string(), errc.message());
"Failed to check if config file exists at {}: {}. Assuming it doesn't.", configPath.string(), errc.message()
);
if (!exists) { if (!exists) {
info_log("Config file not found at {}, creating defaults.", configPath.string()); info_log("Config file not found at {}, creating defaults.", configPath.string());
@ -205,12 +174,15 @@ fn Config::getInstance() -> Config {
const toml::table config = toml::parse_file(configPath.string()); const toml::table config = toml::parse_file(configPath.string());
debug_log("Config loaded from {}", configPath.string()); debug_log("Config loaded from {}", configPath.string());
return Config(config); return Config(config);
} catch (const Exception& e) { } catch (const Exception& e) {
debug_log("Config loading failed: {}, using defaults", e.what()); debug_log("Config loading failed: {}, using defaults", e.what());
return {}; return {};
} catch (...) { } catch (...) {
error_log("An unexpected error occurred during config loading. Using in-memory defaults."); error_log("An unexpected error occurred during config loading. Using in-memory defaults.");
return {}; return {};
} }
} }

View file

@ -47,25 +47,22 @@ struct General {
#ifdef _WIN32 #ifdef _WIN32
// Try to get the username using GetUserNameA // Try to get the username using GetUserNameA
Array<char, 256> username; Array<char, 256> username;
DWORD size = sizeof(username);
DWORD size = username.size();
return GetUserNameA(username.data(), &size) ? username.data() : "User"; return GetUserNameA(username.data(), &size) ? username.data() : "User";
#else #else
using util::helpers::GetEnv; using util::helpers::GetEnv;
// Try to get the username using getpwuid const passwd* pwd = getpwuid(getuid());
if (const passwd* pwd = getpwuid(getuid())) CStr pwdName = pwd ? pwd->pw_name : nullptr;
return pwd->pw_name; const Result<String> envUser = GetEnv("USER");
const Result<String> envLogname = GetEnv("LOGNAME");
// Try to get the username using environment variables return pwdName ? pwdName
if (Result<String> envUser = GetEnv("USER")) : envUser ? *envUser
return *envUser; : envLogname ? *envLogname
: "User";
// Finally, try to get the username using LOGNAME
if (Result<String> envLogname = GetEnv("LOGNAME"))
return *envLogname;
// If all else fails, return a default name
return "User";
#endif #endif
} }

View file

@ -21,10 +21,10 @@ namespace {
using util::types::i32, util::types::CStr; using util::types::i32, util::types::CStr;
fn getOrdinalSuffix(const i32 day) -> CStr { fn getOrdinalSuffix(const i32 day) -> CStr {
using matchit::match, matchit::is, matchit::_, matchit::within; using matchit::match, matchit::is, matchit::_, matchit::in;
return match(day % 10)( return match(day % 10)(
is | within(11, 13) = "th", is | in(11, 13) = "th",
is | 1 = "st", is | 1 = "st",
is | 2 = "nd", is | 2 = "nd",
is | 3 = "rd", is | 3 = "rd",
@ -83,8 +83,12 @@ namespace os {
Future<Result<String>> shellFut = std::async(async, GetShell); Future<Result<String>> shellFut = std::async(async, GetShell);
Future<Result<u64>> pkgFut = std::async(async, GetTotalCount); Future<Result<u64>> pkgFut = std::async(async, GetTotalCount);
Future<Result<MediaInfo>> npFut = std::async(config.nowPlaying.enabled ? async : deferred, GetNowPlaying); Future<Result<MediaInfo>> npFut = std::async(config.nowPlaying.enabled ? async : deferred, GetNowPlaying);
Future<Result<weather::Output>> wthrFut = Future<Result<weather::Output>> wthrFut = std::async(config.weather.enabled ? async : deferred, [&config] {
std::async(config.weather.enabled ? async : deferred, [&config] { return config.weather.getWeatherInfo(); }); return config.weather.getWeatherInfo();
});
{
using enum util::error::DracErrorCode;
this->date = getDate(); this->date = getDate();
this->host = hostFut.get(); this->host = hostFut.get();
@ -96,10 +100,8 @@ namespace os {
this->diskUsage = diskFut.get(); this->diskUsage = diskFut.get();
this->shell = shellFut.get(); this->shell = shellFut.get();
this->packageCount = pkgFut.get(); this->packageCount = pkgFut.get();
this->weather = this->weather = config.weather.enabled ? wthrFut.get() : Err(DracError(ApiUnavailable, "Weather API disabled"));
config.weather.enabled ? wthrFut.get() : Err(DracError(DracErrorCode::ApiUnavailable, "Weather API disabled")); this->nowPlaying = config.nowPlaying.enabled ? npFut.get() : Err(DracError(ApiUnavailable, "Now Playing API disabled"));
this->nowPlaying = config.nowPlaying.enabled }
? npFut.get()
: Err(DracError(DracErrorCode::ApiUnavailable, "Now Playing API disabled"));
} }
} // namespace os } // namespace os