Skip to content

Commit

Permalink
reworked config system, various improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
nightcall489 committed Jan 18, 2025
1 parent 2fb6738 commit 8ee02f9
Show file tree
Hide file tree
Showing 10 changed files with 596 additions and 43 deletions.
32 changes: 20 additions & 12 deletions src/btop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,26 +420,28 @@ void _signal_handler(const int sig) {
//* Config init
void init_config(){
atomic_lock lck(Global::init_conf);
vector<string> load_warnings;
Config::load(Config::conf_file, load_warnings);
Config::set("lowcolor", (Global::arg_low_color ? true : not Config::getB("truecolor")));

g_CfgMgr.load();
(void)g_CfgMgr.set<CfgBool>("lowcolor", Global::arg_low_color
? true
: !g_CfgMgr.get<CfgBool>("truecolor").value());

static bool first_init = true;

if (Global::debug and first_init) {
Logger::set("DEBUG");
Logger::debug("Running in DEBUG mode!");
}
else Logger::set(Config::getS("log_level"));
} else {
Logger::set(Config::getS("log_level"));
}

static string log_level;
if (const string current_level = Config::getS("log_level"); log_level != current_level) {
log_level = current_level;
Logger::info("Logger set to " + (Global::debug ? "DEBUG" : log_level));
}

for (const auto& err_str : load_warnings) Logger::warning(err_str);
first_init = false;
first_init = false;
}

//* Manages secondary thread for collection and drawing of boxes
Expand Down Expand Up @@ -859,7 +861,8 @@ namespace Runner {
current_conf = {
(box == "all" ? Config::current_boxes : vector{box}),
no_update, force_redraw,
(not Config::getB("tty_mode") and Config::getB("background_update")),
(!g_CfgMgr.get<CfgBool>("tty_mode").value()
&& g_CfgMgr.get<CfgBool>("background_update").value()),
Global::overlay,
Global::clock
};
Expand Down Expand Up @@ -906,9 +909,14 @@ namespace Runner {

//* --------------------------------------------- Main starts here! ---------------------------------------------------
int main(int argc, char **argv) {
if (!g_CfgMgr.init()) {
std::cout << "Failed to load default configuration" << std::endl;
return 1;
}
g_CfgMgr.load();

//? ------------------------------------------------ INIT ---------------------------------------------------------

Global::start_time = time_s();

//? Save real and effective userid's and drop privileges until needed if running with SUID bit set
Expand Down Expand Up @@ -1046,7 +1054,7 @@ int main(int argc, char **argv) {
}

if (Term::current_tty != "unknown") Logger::info("Running on " + Term::current_tty);
if (not Global::arg_tty and Config::getB("force_tty")) {
if (not Global::arg_tty && g_CfgMgr.get<CfgBool>("force_tty").value()) {
Config::set("tty_mode", true);
Logger::info("Forcing tty mode: setting 16 color mode and using tty friendly graph symbols");
}
Expand Down Expand Up @@ -1079,7 +1087,7 @@ int main(int argc, char **argv) {
clean_quit(1);
}

if (not Config::set_boxes(Config::getS("shown_boxes"))) {
if (!Config::set_boxes(g_CfgMgr.get<CfgString>("shown_boxes").value())) {
Config::set_boxes("cpu mem net proc");
Config::set("shown_boxes", "cpu mem net proc"s);
}
Expand Down Expand Up @@ -1141,7 +1149,7 @@ int main(int argc, char **argv) {
if (Global::arg_update != 0) {
Config::set("update_ms", Global::arg_update);
}
uint64_t update_ms = Config::getI("update_ms");
uint64_t update_ms = g_CfgMgr.get<CfgInt>("update_ms").value();
auto future_time = time_ms();

try {
Expand Down
117 changes: 117 additions & 0 deletions src/btop_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ tab-size = 4
#include <ranges>
#include <string_view>
#include <utility>
#include <iostream>

#include <fmt/core.h>
#include <sys/statvfs.h>
Expand All @@ -40,6 +41,122 @@ namespace rng = std::ranges;
using namespace std::literals;
using namespace Tools;

//////////////////// TEMPORARY UTILITY ROUTINES ///////////////////////////////

static std::string trim_str(std::string str) {
str.erase(str.begin(),
std::find_if(str.begin(),
str.end(),
[](unsigned char ch) { return !std::isspace(ch); }));
str.erase(std::find_if(str.rbegin(),
str.rend(),
[](unsigned char ch) { return !std::isspace(ch); }).base(),
str.end());
return str;
}
///////////////////////////////////////////////////////////////////////////////

CfgManager g_CfgMgr("conf.ini");

CfgManager::CfgManager(const std::string& cfg_path) {
cfg_file = std::filesystem::path(cfg_path);
setup_validators();
}

bool CfgManager::load() {
auto is_valid = [](const std::string& line) {
return !line.empty() && !line.starts_with(';') && !line.starts_with('#');
};

auto key_present = [&](const std::string& key) {
return cfg_keys.find(key) != cfg_keys.end();
};

std::ifstream file(cfg_file);
if (!file) {
return false;
}

bool tainted = false;
std::string line;
size_t line_num = 0;

while (std::getline(file, line)) {
++line_num;
line = trim_str(line);

if (!is_valid(line)) {
continue;
}

auto eq = line.find('=');
if (eq == std::string::npos) {
continue;
}

std::string k = trim_str(line.substr(0, eq));
std::string v = trim_str(line.substr(eq + 1));

if (k.empty() || v.empty()) {
continue;
}

if (!key_present(k)) {
continue;
}

auto it = cfg_keys.find(k);
CfgResult<bool> result = [this, &k, &v, type = it->second.type]() -> CfgResult<bool> {
switch(type) {
case CString:
return try_set<CfgString>(k, v);
case CBool:
return try_set<CfgBool>(k, v);
case CInt:
return try_set<CfgInt>(k, v);
default:
return CfgResult<bool>("Unknown configuration type");
}
}();

if (result.is_error()) {
std::cerr << "Error on line " << line_num << ": "
<< result.error() << " (key: " << k << ", val: " << v << ")"
<< std::endl;
tainted = true;
}
}
return tainted;
}

bool CfgManager::init() {
bool success = true;

for (const auto& [k, i] : cfg_keys) {
auto set_result = std::visit([this, &k](const auto& def) -> CfgResult<bool> {
using T = std::decay_t<decltype(def)>;

if constexpr (std::is_same_v<T, CfgString>) {
return set<CfgString>(k, def);
} else if constexpr (std::is_same_v<T, CfgBool>) {
return set<CfgBool>(k, def);
} else if constexpr (std::is_same_v<T, CfgInt>) {
return set<CfgInt>(k, def);
} else {
return CfgResult<bool>("Unsupported configuration type");
}
}, i.def);

if (set_result.is_error()) {
std::cerr << "Error setting default value for key '" << k
<< "': " << set_result.error() << '\n';
success = false;
}
}
return success;
}


//* Functions and variables for reading and writing the btop config file
namespace Config {

Expand Down
Loading

0 comments on commit 8ee02f9

Please sign in to comment.