mirror of
https://github.com/obsqrbtz/clrsync.git
synced 2026-04-09 04:29:04 +03:00
refactor: error handling with err objects
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#include <argparse/argparse.hpp>
|
#include <argparse/argparse.hpp>
|
||||||
|
|
||||||
#include <core/config/config.hpp>
|
#include <core/config/config.hpp>
|
||||||
|
#include <core/error.hpp>
|
||||||
#include <core/io/toml_file.hpp>
|
#include <core/io/toml_file.hpp>
|
||||||
#include <core/palette/palette_file.hpp>
|
#include <core/palette/palette_file.hpp>
|
||||||
#include <core/palette/palette_manager.hpp>
|
#include <core/palette/palette_manager.hpp>
|
||||||
@@ -35,16 +36,17 @@ int handle_apply_theme(const argparse::ArgumentParser &program, const std::strin
|
|||||||
{
|
{
|
||||||
clrsync::core::theme_renderer<clrsync::core::io::toml_file> renderer;
|
clrsync::core::theme_renderer<clrsync::core::io::toml_file> renderer;
|
||||||
std::string theme_identifier;
|
std::string theme_identifier;
|
||||||
|
clrsync::core::Result<void> result = clrsync::core::Ok();
|
||||||
|
|
||||||
if (program.is_used("--theme"))
|
if (program.is_used("--theme"))
|
||||||
{
|
{
|
||||||
theme_identifier = program.get<std::string>("--theme");
|
theme_identifier = program.get<std::string>("--theme");
|
||||||
renderer.apply_theme(theme_identifier);
|
result = renderer.apply_theme(theme_identifier);
|
||||||
}
|
}
|
||||||
else if (program.is_used("--path"))
|
else if (program.is_used("--path"))
|
||||||
{
|
{
|
||||||
theme_identifier = program.get<std::string>("--path");
|
theme_identifier = program.get<std::string>("--path");
|
||||||
renderer.apply_theme_from_path(theme_identifier);
|
result = renderer.apply_theme_from_path(theme_identifier);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -54,17 +56,23 @@ int handle_apply_theme(const argparse::ArgumentParser &program, const std::strin
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
theme_identifier = default_theme;
|
theme_identifier = default_theme;
|
||||||
renderer.apply_theme(theme_identifier);
|
result = renderer.apply_theme(theme_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to apply theme: " << result.error().description() << std::endl;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Applied theme " << theme_identifier << std::endl;
|
std::cout << "Applied theme " << theme_identifier << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_config(const std::string &config_path)
|
clrsync::core::Result<void> initialize_config(const std::string &config_path)
|
||||||
{
|
{
|
||||||
auto conf = std::make_unique<clrsync::core::io::toml_file>(config_path);
|
auto conf = std::make_unique<clrsync::core::io::toml_file>(config_path);
|
||||||
clrsync::core::config::instance().initialize(std::move(conf));
|
return clrsync::core::config::instance().initialize(std::move(conf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_argument_parser(argparse::ArgumentParser &program)
|
void setup_argument_parser(argparse::ArgumentParser &program)
|
||||||
@@ -103,13 +111,10 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
std::string config_path = program.get<std::string>("--config");
|
std::string config_path = program.get<std::string>("--config");
|
||||||
|
|
||||||
try
|
auto config_result = initialize_config(config_path);
|
||||||
|
if (!config_result)
|
||||||
{
|
{
|
||||||
initialize_config(config_path);
|
std::cerr << "Error loading config: " << config_result.error().description() << std::endl;
|
||||||
}
|
|
||||||
catch (const std::exception &err)
|
|
||||||
{
|
|
||||||
std::cerr << "Error loading config: " << err.what() << std::endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "core/utils.hpp"
|
#include "core/utils.hpp"
|
||||||
|
#include "core/error.hpp"
|
||||||
|
|
||||||
#include <core/palette/color.hpp>
|
#include <core/palette/color.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
@@ -19,14 +19,18 @@ config &config::instance()
|
|||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::initialize(std::unique_ptr<clrsync::core::io::file> file)
|
Result<void> config::initialize(std::unique_ptr<clrsync::core::io::file> file)
|
||||||
{
|
{
|
||||||
copy_default_configs();
|
copy_default_configs();
|
||||||
m_file = std::move(file);
|
m_file = std::move(file);
|
||||||
if (!m_file)
|
if (!m_file)
|
||||||
throw std::runtime_error{"Config file is missing"};
|
return Err<void>(error_code::config_missing, "Config file is missing");
|
||||||
if (!m_file->parse())
|
|
||||||
throw std::runtime_error{"Could not parse config file"};
|
auto parse_result = m_file->parse();
|
||||||
|
if (!parse_result)
|
||||||
|
return Err<void>(error_code::config_invalid, parse_result.error().message, parse_result.error().context);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path config::get_user_config_dir()
|
std::filesystem::path config::get_user_config_dir()
|
||||||
@@ -65,19 +69,13 @@ void config::copy_file(const std::filesystem::path &src, const std::filesystem::
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!std::filesystem::exists(src))
|
if (!std::filesystem::exists(src))
|
||||||
{
|
|
||||||
std::cerr << "Warning: Source file does not exist: " << src << std::endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream in(src, std::ios::binary);
|
std::ifstream in(src, std::ios::binary);
|
||||||
std::ofstream out(dst, std::ios::binary);
|
std::ofstream out(dst, std::ios::binary);
|
||||||
|
|
||||||
if (!in || !out)
|
if (!in || !out)
|
||||||
{
|
|
||||||
std::cerr << "Warning: Failed to copy file from " << src << " to " << dst << std::endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
out << in.rdbuf();
|
out << in.rdbuf();
|
||||||
}
|
}
|
||||||
@@ -85,10 +83,7 @@ void config::copy_file(const std::filesystem::path &src, const std::filesystem::
|
|||||||
void config::copy_dir(const std::filesystem::path &src, const std::filesystem::path &dst)
|
void config::copy_dir(const std::filesystem::path &src, const std::filesystem::path &dst)
|
||||||
{
|
{
|
||||||
if (!std::filesystem::exists(src))
|
if (!std::filesystem::exists(src))
|
||||||
{
|
|
||||||
std::cerr << "Warning: Source directory does not exist: " << src << std::endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const &entry : std::filesystem::recursive_directory_iterator(src))
|
for (auto const &entry : std::filesystem::recursive_directory_iterator(src))
|
||||||
{
|
{
|
||||||
@@ -114,10 +109,7 @@ void config::copy_default_configs()
|
|||||||
std::filesystem::create_directories(user_dir);
|
std::filesystem::create_directories(user_dir);
|
||||||
|
|
||||||
if (system_dir.empty())
|
if (system_dir.empty())
|
||||||
{
|
|
||||||
std::cerr << "Warning: No system data directory found, skipping default config copy\n";
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto src = system_dir / "config.toml";
|
auto src = system_dir / "config.toml";
|
||||||
@@ -175,50 +167,53 @@ const uint32_t config::font_size() const
|
|||||||
return 14;
|
return 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::set_default_theme(const std::string &theme)
|
Result<void> config::set_default_theme(const std::string &theme)
|
||||||
{
|
{
|
||||||
if (m_file)
|
if (!m_file)
|
||||||
{
|
return Err<void>(error_code::config_missing, "Configuration not initialized");
|
||||||
m_file->set_value("general", "default_theme", theme);
|
|
||||||
m_file->save_file();
|
m_file->set_value("general", "default_theme", theme);
|
||||||
}
|
return m_file->save_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::set_palettes_path(const std::string &path)
|
Result<void> config::set_palettes_path(const std::string &path)
|
||||||
{
|
{
|
||||||
if (m_file)
|
if (!m_file)
|
||||||
{
|
return Err<void>(error_code::config_missing, "Configuration not initialized");
|
||||||
m_file->set_value("general", "palettes_path", path);
|
|
||||||
m_file->save_file();
|
m_file->set_value("general", "palettes_path", path);
|
||||||
}
|
return m_file->save_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::set_font(const std::string &font)
|
Result<void> config::set_font(const std::string &font)
|
||||||
{
|
{
|
||||||
if (m_file)
|
if (!m_file)
|
||||||
{
|
return Err<void>(error_code::config_missing, "Configuration not initialized");
|
||||||
m_file->set_value("general", "font", font);
|
|
||||||
m_file->save_file();
|
m_file->set_value("general", "font", font);
|
||||||
}
|
return m_file->save_file();
|
||||||
}
|
}
|
||||||
void config::set_font_size(int font_size)
|
Result<void> config::set_font_size(int font_size)
|
||||||
{
|
{
|
||||||
if (m_file)
|
if (!m_file)
|
||||||
{
|
return Err<void>(error_code::config_missing, "Configuration not initialized");
|
||||||
m_file->set_value("general", "font_size", font_size);
|
|
||||||
m_file->save_file();
|
m_file->set_value("general", "font_size", font_size);
|
||||||
}
|
return m_file->save_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::update_template(const std::string &key,
|
Result<void> config::update_template(const std::string &key,
|
||||||
const clrsync::core::theme_template &theme_template)
|
const clrsync::core::theme_template &theme_template)
|
||||||
{
|
{
|
||||||
|
if (!m_file)
|
||||||
|
return Err<void>(error_code::config_missing, "Configuration not initialized");
|
||||||
|
|
||||||
m_themes[key] = theme_template;
|
m_themes[key] = theme_template;
|
||||||
m_file->set_value("templates." + key, "input_path", theme_template.template_path());
|
m_file->set_value("templates." + key, "input_path", theme_template.template_path());
|
||||||
m_file->set_value("templates." + key, "output_path", theme_template.output_path());
|
m_file->set_value("templates." + key, "output_path", theme_template.output_path());
|
||||||
m_file->set_value("templates." + key, "enabled", theme_template.enabled());
|
m_file->set_value("templates." + key, "enabled", theme_template.enabled());
|
||||||
m_file->set_value("templates." + key, "reload_cmd", theme_template.reload_command());
|
m_file->set_value("templates." + key, "reload_cmd", theme_template.reload_command());
|
||||||
m_file->save_file();
|
return m_file->save_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_map<std::string, clrsync::core::theme_template> config::templates()
|
const std::unordered_map<std::string, clrsync::core::theme_template> config::templates()
|
||||||
@@ -241,21 +236,21 @@ const std::unordered_map<std::string, clrsync::core::theme_template> config::tem
|
|||||||
theme.set_enabled(false);
|
theme.set_enabled(false);
|
||||||
}
|
}
|
||||||
theme.set_reload_command(std::get<std::string>(current["reload_cmd"]));
|
theme.set_reload_command(std::get<std::string>(current["reload_cmd"]));
|
||||||
theme.load_template();
|
(void)theme.load_template();
|
||||||
m_themes.insert({theme.name(), theme});
|
m_themes.insert({theme.name(), theme});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_themes;
|
return m_themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const clrsync::core::theme_template &config::template_by_name(const std::string &name) const
|
Result<const clrsync::core::theme_template*> config::template_by_name(const std::string &name) const
|
||||||
{
|
{
|
||||||
auto it = m_themes.find(name);
|
auto it = m_themes.find(name);
|
||||||
if (it != m_themes.end())
|
if (it != m_themes.end())
|
||||||
{
|
{
|
||||||
return it->second;
|
return Ok(&it->second);
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Template not found: " + name);
|
return Err<const clrsync::core::theme_template*>(error_code::template_not_found, "Template not found", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace clrsync::core
|
} // namespace clrsync::core
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <core/io/file.hpp>
|
#include <core/io/file.hpp>
|
||||||
#include <core/theme/theme_template.hpp>
|
#include <core/theme/theme_template.hpp>
|
||||||
|
#include <core/error.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -14,23 +15,23 @@ class config
|
|||||||
public:
|
public:
|
||||||
static config &instance();
|
static config &instance();
|
||||||
|
|
||||||
void initialize(std::unique_ptr<clrsync::core::io::file> file);
|
Result<void> initialize(std::unique_ptr<clrsync::core::io::file> file);
|
||||||
|
|
||||||
const std::string font() const;
|
const std::string font() const;
|
||||||
const uint32_t font_size() const;
|
const uint32_t font_size() const;
|
||||||
const std::string &palettes_path();
|
const std::string &palettes_path();
|
||||||
const std::string default_theme() const;
|
const std::string default_theme() const;
|
||||||
const std::unordered_map<std::string, clrsync::core::theme_template> templates();
|
const std::unordered_map<std::string, clrsync::core::theme_template> templates();
|
||||||
const clrsync::core::theme_template &template_by_name(const std::string &name) const;
|
Result<const clrsync::core::theme_template*> template_by_name(const std::string &name) const;
|
||||||
std::filesystem::path get_user_config_dir();
|
std::filesystem::path get_user_config_dir();
|
||||||
|
|
||||||
|
|
||||||
void set_default_theme(const std::string &theme);
|
Result<void> set_default_theme(const std::string &theme);
|
||||||
void set_palettes_path(const std::string &path);
|
Result<void> set_palettes_path(const std::string &path);
|
||||||
void set_font(const std::string &font);
|
Result<void> set_font(const std::string &font);
|
||||||
void set_font_size(int font_size);
|
Result<void> set_font_size(int font_size);
|
||||||
|
|
||||||
void update_template(const std::string &key,
|
Result<void> update_template(const std::string &key,
|
||||||
const clrsync::core::theme_template &theme_template);
|
const clrsync::core::theme_template &theme_template);
|
||||||
static std::filesystem::path get_data_dir();
|
static std::filesystem::path get_data_dir();
|
||||||
|
|
||||||
|
|||||||
207
src/core/error.hpp
Normal file
207
src/core/error.hpp
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
#ifndef CLRSYNC_CORE_ERROR_HPP
|
||||||
|
#define CLRSYNC_CORE_ERROR_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace clrsync::core
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class error_code
|
||||||
|
{
|
||||||
|
unknown,
|
||||||
|
|
||||||
|
file_not_found,
|
||||||
|
file_open_failed,
|
||||||
|
file_write_failed,
|
||||||
|
file_read_failed,
|
||||||
|
dir_create_failed,
|
||||||
|
|
||||||
|
parse_failed,
|
||||||
|
invalid_format,
|
||||||
|
|
||||||
|
config_missing,
|
||||||
|
config_invalid,
|
||||||
|
|
||||||
|
template_not_found,
|
||||||
|
template_load_failed,
|
||||||
|
template_apply_failed,
|
||||||
|
|
||||||
|
palette_not_found,
|
||||||
|
palette_load_failed,
|
||||||
|
|
||||||
|
init_failed,
|
||||||
|
invalid_arg,
|
||||||
|
resource_missing,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* error_code_string(error_code code)
|
||||||
|
{
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case error_code::unknown: return "Unknown error";
|
||||||
|
case error_code::file_not_found: return "File not found";
|
||||||
|
case error_code::file_open_failed: return "Failed to open file";
|
||||||
|
case error_code::file_write_failed: return "Failed to write file";
|
||||||
|
case error_code::file_read_failed: return "Failed to read file";
|
||||||
|
case error_code::dir_create_failed: return "Failed to create directory";
|
||||||
|
case error_code::parse_failed: return "Parse failed";
|
||||||
|
case error_code::invalid_format: return "Invalid format";
|
||||||
|
case error_code::config_missing: return "Configuration missing";
|
||||||
|
case error_code::config_invalid: return "Configuration invalid";
|
||||||
|
case error_code::template_not_found: return "Template not found";
|
||||||
|
case error_code::template_load_failed: return "Failed to load template";
|
||||||
|
case error_code::template_apply_failed: return "Failed to apply template";
|
||||||
|
case error_code::palette_not_found: return "Palette not found";
|
||||||
|
case error_code::palette_load_failed: return "Failed to load palette";
|
||||||
|
case error_code::init_failed: return "Initialization failed";
|
||||||
|
case error_code::invalid_arg: return "Invalid argument";
|
||||||
|
case error_code::resource_missing: return "Resource missing";
|
||||||
|
default: return "Unknown error code";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Error
|
||||||
|
{
|
||||||
|
error_code code;
|
||||||
|
std::string message;
|
||||||
|
std::string context;
|
||||||
|
|
||||||
|
Error(error_code c) : code(c), message(error_code_string(c)) {}
|
||||||
|
|
||||||
|
Error(error_code c, std::string msg)
|
||||||
|
: code(c), message(std::move(msg)) {}
|
||||||
|
|
||||||
|
Error(error_code c, std::string msg, std::string ctx)
|
||||||
|
: code(c), message(std::move(msg)), context(std::move(ctx)) {}
|
||||||
|
|
||||||
|
std::string description() const
|
||||||
|
{
|
||||||
|
if (context.empty())
|
||||||
|
return message;
|
||||||
|
return message + " [" + context + "]";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class [[nodiscard]] Result
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::variant<T, Error> m_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Result(T value) : m_data(std::move(value)) {}
|
||||||
|
|
||||||
|
Result(Error error) : m_data(std::move(error)) {}
|
||||||
|
|
||||||
|
bool is_ok() const { return std::holds_alternative<T>(m_data); }
|
||||||
|
|
||||||
|
bool is_error() const { return std::holds_alternative<Error>(m_data); }
|
||||||
|
|
||||||
|
explicit operator bool() const { return is_ok(); }
|
||||||
|
|
||||||
|
T& value() & { return std::get<T>(m_data); }
|
||||||
|
const T& value() const & { return std::get<T>(m_data); }
|
||||||
|
T&& value() && { return std::get<T>(std::move(m_data)); }
|
||||||
|
|
||||||
|
const Error& error() const { return std::get<Error>(m_data); }
|
||||||
|
|
||||||
|
T value_or(T default_value) const
|
||||||
|
{
|
||||||
|
return is_ok() ? std::get<T>(m_data) : std::move(default_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<T> ok() const
|
||||||
|
{
|
||||||
|
if (is_ok())
|
||||||
|
return std::get<T>(m_data);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Error> err() const
|
||||||
|
{
|
||||||
|
if (is_error())
|
||||||
|
return std::get<Error>(m_data);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
auto map(F&& func) -> Result<decltype(func(std::declval<T>()))>
|
||||||
|
{
|
||||||
|
using U = decltype(func(std::declval<T>()));
|
||||||
|
if (is_ok())
|
||||||
|
return Result<U>(func(std::get<T>(m_data)));
|
||||||
|
return Result<U>(std::get<Error>(m_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
auto and_then(F&& func) -> decltype(func(std::declval<T>()))
|
||||||
|
{
|
||||||
|
if (is_ok())
|
||||||
|
return func(std::get<T>(m_data));
|
||||||
|
using ResultType = decltype(func(std::declval<T>()));
|
||||||
|
return ResultType(std::get<Error>(m_data));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class [[nodiscard]] Result<void>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::optional<Error> m_error;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Result() : m_error(std::nullopt) {}
|
||||||
|
|
||||||
|
Result(Error error) : m_error(std::move(error)) {}
|
||||||
|
|
||||||
|
bool is_ok() const { return !m_error.has_value(); }
|
||||||
|
|
||||||
|
bool is_error() const { return m_error.has_value(); }
|
||||||
|
|
||||||
|
explicit operator bool() const { return is_ok(); }
|
||||||
|
|
||||||
|
const Error& error() const { return *m_error; }
|
||||||
|
|
||||||
|
std::optional<Error> err() const { return m_error; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Result<T> Ok(T value)
|
||||||
|
{
|
||||||
|
return Result<T>(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Result<void> Ok()
|
||||||
|
{
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Result<T> Err(Error error)
|
||||||
|
{
|
||||||
|
return Result<T>(std::move(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Result<T> Err(error_code code)
|
||||||
|
{
|
||||||
|
return Result<T>(Error(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Result<T> Err(error_code code, std::string message)
|
||||||
|
{
|
||||||
|
return Result<T>(Error(code, std::move(message)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Result<T> Err(error_code code, std::string message, std::string context)
|
||||||
|
{
|
||||||
|
return Result<T>(Error(code, std::move(message), std::move(context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace clrsync::core
|
||||||
|
|
||||||
|
#endif // CLRSYNC_CORE_ERROR_HPP
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <core/error.hpp>
|
||||||
|
|
||||||
using value_type = std::variant<std::string, uint32_t, int, bool>;
|
using value_type = std::variant<std::string, uint32_t, int, bool>;
|
||||||
|
|
||||||
@@ -14,7 +15,8 @@ class file
|
|||||||
public:
|
public:
|
||||||
file() = default;
|
file() = default;
|
||||||
file(std::string path) {};
|
file(std::string path) {};
|
||||||
virtual bool parse() { return false; };
|
virtual ~file() = default;
|
||||||
|
virtual Result<void> parse() { return Ok(); };
|
||||||
virtual const std::string get_string_value(const std::string §ion,
|
virtual const std::string get_string_value(const std::string §ion,
|
||||||
const std::string &key) const
|
const std::string &key) const
|
||||||
{
|
{
|
||||||
@@ -39,7 +41,7 @@ class file
|
|||||||
}
|
}
|
||||||
virtual void insert_or_update_value(const std::string §ion, const std::string &key,
|
virtual void insert_or_update_value(const std::string §ion, const std::string &key,
|
||||||
const value_type &value) {};
|
const value_type &value) {};
|
||||||
virtual void save_file() {};
|
virtual Result<void> save_file() { return Ok(); };
|
||||||
};
|
};
|
||||||
} // namespace clrsync::core::io
|
} // namespace clrsync::core::io
|
||||||
#endif
|
#endif
|
||||||
@@ -11,12 +11,13 @@ toml_file::toml_file(std::string path)
|
|||||||
m_path = expand_user(path);
|
m_path = expand_user(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool toml_file::parse()
|
Result<void> toml_file::parse()
|
||||||
{
|
{
|
||||||
if (!std::filesystem::exists(m_path))
|
if (!std::filesystem::exists(m_path))
|
||||||
return false;
|
return Err<void>(error_code::file_not_found, "File does not exist", m_path);
|
||||||
|
|
||||||
m_file = toml::parse_file(m_path);
|
m_file = toml::parse_file(m_path);
|
||||||
return true;
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string toml_file::get_string_value(const std::string §ion,
|
const std::string toml_file::get_string_value(const std::string §ion,
|
||||||
@@ -91,11 +92,23 @@ void toml_file::insert_or_update_value(const std::string §ion, const std::st
|
|||||||
std::visit([&](auto &&v) { tbl->insert_or_assign(key, v); }, value);
|
std::visit([&](auto &&v) { tbl->insert_or_assign(key, v); }, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toml_file::save_file()
|
Result<void> toml_file::save_file()
|
||||||
{
|
{
|
||||||
std::filesystem::create_directories(std::filesystem::path(m_path).parent_path());
|
try {
|
||||||
|
std::filesystem::create_directories(std::filesystem::path(m_path).parent_path());
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
return Err<void>(error_code::dir_create_failed, e.what(), m_path);
|
||||||
|
}
|
||||||
|
|
||||||
std::ofstream stream(m_path, std::ios::binary);
|
std::ofstream stream(m_path, std::ios::binary);
|
||||||
|
if (!stream)
|
||||||
|
return Err<void>(error_code::file_write_failed, "Failed to open file for writing", m_path);
|
||||||
|
|
||||||
stream << m_file;
|
stream << m_file;
|
||||||
|
if (!stream)
|
||||||
|
return Err<void>(error_code::file_write_failed, "Failed to write to file", m_path);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> toml_file::split(const std::string &s, char delim) const
|
std::vector<std::string> toml_file::split(const std::string &s, char delim) const
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef CLRSYNC_CORE_IO_TOML_FILE_HPP
|
#ifndef CLRSYNC_CORE_IO_TOML_FILE_HPP
|
||||||
#define CLRSYNC_CORE_IO_TOML_FILE_HPP
|
#define CLRSYNC_CORE_IO_TOML_FILE_HPP
|
||||||
#include <core/io/file.hpp>
|
#include <core/io/file.hpp>
|
||||||
|
#include <core/error.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <toml/toml.hpp>
|
#include <toml/toml.hpp>
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ class toml_file : public file
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit toml_file(std::string path);
|
explicit toml_file(std::string path);
|
||||||
bool parse() override;
|
Result<void> parse() override;
|
||||||
const std::string get_string_value(const std::string §ion,
|
const std::string get_string_value(const std::string §ion,
|
||||||
const std::string &key) const override;
|
const std::string &key) const override;
|
||||||
uint32_t get_uint_value(const std::string §ion, const std::string &key) const override;
|
uint32_t get_uint_value(const std::string §ion, const std::string &key) const override;
|
||||||
@@ -18,7 +19,7 @@ class toml_file : public file
|
|||||||
std::map<std::string, value_type> get_table(const std::string §ion_path) const override;
|
std::map<std::string, value_type> get_table(const std::string §ion_path) const override;
|
||||||
void insert_or_update_value(const std::string §ion, const std::string &key,
|
void insert_or_update_value(const std::string §ion, const std::string &key,
|
||||||
const value_type &value) override;
|
const value_type &value) override;
|
||||||
void save_file() override;
|
Result<void> save_file() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
toml::parse_result m_file{};
|
toml::parse_result m_file{};
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ template <typename FileType> class palette_file
|
|||||||
}
|
}
|
||||||
void save()
|
void save()
|
||||||
{
|
{
|
||||||
m_file->save_file();
|
(void)m_file->save_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ template <typename FileType> class palette_manager
|
|||||||
{
|
{
|
||||||
auto directory_path_expanded = expand_user(directory_path);
|
auto directory_path_expanded = expand_user(directory_path);
|
||||||
if (!std::filesystem::exists(directory_path_expanded))
|
if (!std::filesystem::exists(directory_path_expanded))
|
||||||
{
|
|
||||||
std::cerr << "Palettes directory does not exist\n" ;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
for (const auto &entry : std::filesystem::directory_iterator(directory_path_expanded))
|
for (const auto &entry : std::filesystem::directory_iterator(directory_path_expanded))
|
||||||
{
|
{
|
||||||
if (entry.is_regular_file())
|
if (entry.is_regular_file())
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <core/config/config.hpp>
|
#include <core/config/config.hpp>
|
||||||
#include <core/palette/palette_manager.hpp>
|
#include <core/palette/palette_manager.hpp>
|
||||||
#include <core/theme/template_manager.hpp>
|
#include <core/theme/template_manager.hpp>
|
||||||
|
#include <core/error.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace clrsync::core
|
namespace clrsync::core
|
||||||
@@ -18,38 +19,52 @@ template <typename FileType> class theme_renderer
|
|||||||
m_template_manager = template_manager<FileType>();
|
m_template_manager = template_manager<FileType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_theme(const std::string &theme_name)
|
Result<void> apply_theme(const std::string &theme_name)
|
||||||
{
|
{
|
||||||
auto palette = m_pal_manager.get_palette(theme_name);
|
auto palette = m_pal_manager.get_palette(theme_name);
|
||||||
if (!palette)
|
if (!palette)
|
||||||
throw std::runtime_error("Palette not found: " + theme_name);
|
return Err<void>(error_code::palette_not_found, "Palette not found", theme_name);
|
||||||
apply_palette_to_all_templates(*palette);
|
return apply_palette_to_all_templates(*palette);
|
||||||
}
|
}
|
||||||
void apply_theme_from_path(const std::string &path)
|
|
||||||
|
Result<void> apply_theme_from_path(const std::string &path)
|
||||||
{
|
{
|
||||||
auto palette = m_pal_manager.load_palette_from_file(path);
|
auto palette = m_pal_manager.load_palette_from_file(path);
|
||||||
apply_palette_to_all_templates(palette);
|
return apply_palette_to_all_templates(palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
palette_manager<FileType> m_pal_manager;
|
palette_manager<FileType> m_pal_manager;
|
||||||
template_manager<FileType> m_template_manager;
|
template_manager<FileType> m_template_manager;
|
||||||
|
|
||||||
void apply_palette_to_all_templates(const palette &pal)
|
Result<void> apply_palette_to_all_templates(const palette &pal)
|
||||||
{
|
{
|
||||||
for (auto &t_pair : m_template_manager.templates())
|
for (auto &t_pair : m_template_manager.templates())
|
||||||
{
|
{
|
||||||
auto &tmpl = t_pair.second;
|
auto &tmpl = t_pair.second;
|
||||||
if (!tmpl.enabled())
|
if (!tmpl.enabled())
|
||||||
continue;
|
continue;
|
||||||
tmpl.load_template();
|
|
||||||
|
auto load_result = tmpl.load_template();
|
||||||
|
if (!load_result)
|
||||||
|
return load_result;
|
||||||
|
|
||||||
tmpl.apply_palette(pal);
|
tmpl.apply_palette(pal);
|
||||||
tmpl.save_output();
|
|
||||||
|
auto save_result = tmpl.save_output();
|
||||||
|
if (!save_result)
|
||||||
|
return save_result;
|
||||||
|
|
||||||
if (!tmpl.reload_command().empty())
|
if (!tmpl.reload_command().empty())
|
||||||
{
|
{
|
||||||
std::system(tmpl.reload_command().c_str());
|
int result = std::system(tmpl.reload_command().c_str());
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
std::cerr << "Warning: Command " << tmpl.reload_command() << " failed with code " << result << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,21 +43,21 @@ void theme_template::set_output_path(const std::string &path)
|
|||||||
m_output_path = expand_user(path);
|
m_output_path = expand_user(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void theme_template::load_template()
|
Result<void> theme_template::load_template()
|
||||||
{
|
{
|
||||||
if (!std::filesystem::exists(m_template_path))
|
if (!std::filesystem::exists(m_template_path))
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Template file '" << m_template_path << "' is missing\n";
|
return Err<void>(error_code::template_not_found, "Template file is missing", m_template_path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream input(m_template_path, std::ios::binary);
|
std::ifstream input(m_template_path, std::ios::binary);
|
||||||
if (!input)
|
if (!input)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Failed to open template file: " << m_template_path << std::endl;
|
return Err<void>(error_code::template_load_failed, "Failed to open template file", m_template_path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_template_data.assign(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>());
|
m_template_data.assign(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>());
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
void theme_template::apply_palette(const core::palette &palette)
|
void theme_template::apply_palette(const core::palette &palette)
|
||||||
@@ -90,7 +90,7 @@ void theme_template::apply_palette(const core::palette &palette)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void theme_template::save_output() const
|
Result<void> theme_template::save_output() const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -98,18 +98,22 @@ void theme_template::save_output() const
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Failed to create output directory for " << m_output_path << ": " << e.what() << std::endl;
|
return Err<void>(error_code::dir_create_failed, e.what(), m_output_path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream output(m_output_path, std::ios::binary);
|
std::ofstream output(m_output_path, std::ios::binary);
|
||||||
if (!output)
|
if (!output)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Failed to write output file: " << m_output_path << std::endl;
|
return Err<void>(error_code::file_write_failed, "Failed to open output file for writing", m_output_path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output << m_processed_data;
|
output << m_processed_data;
|
||||||
|
if (!output)
|
||||||
|
{
|
||||||
|
return Err<void>(error_code::file_write_failed, "Failed to write to output file", m_output_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &theme_template::raw_template() const
|
const std::string &theme_template::raw_template() const
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define clrsync_CORE_IO_THEME_TEMPLATE_HPP
|
#define clrsync_CORE_IO_THEME_TEMPLATE_HPP
|
||||||
|
|
||||||
#include <core/palette/palette.hpp>
|
#include <core/palette/palette.hpp>
|
||||||
|
#include <core/error.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace clrsync::core
|
namespace clrsync::core
|
||||||
@@ -26,11 +27,11 @@ class theme_template
|
|||||||
|
|
||||||
void set_output_path(const std::string &path);
|
void set_output_path(const std::string &path);
|
||||||
|
|
||||||
void load_template();
|
Result<void> load_template();
|
||||||
|
|
||||||
void apply_palette(const core::palette &palette);
|
void apply_palette(const core::palette &palette);
|
||||||
|
|
||||||
void save_output() const;
|
Result<void> save_output() const;
|
||||||
|
|
||||||
const std::string &raw_template() const;
|
const std::string &raw_template() const;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "core/config/config.hpp"
|
#include "core/config/config.hpp"
|
||||||
#include "core/io/toml_file.hpp"
|
#include "core/io/toml_file.hpp"
|
||||||
#include "core/utils.hpp"
|
#include "core/utils.hpp"
|
||||||
|
#include "core/error.hpp"
|
||||||
|
|
||||||
#include "color_scheme_editor.hpp"
|
#include "color_scheme_editor.hpp"
|
||||||
#include "gui/font_loader.hpp"
|
#include "gui/font_loader.hpp"
|
||||||
@@ -21,13 +22,10 @@ int main(int, char**)
|
|||||||
auto config_path = clrsync::core::get_default_config_path();
|
auto config_path = clrsync::core::get_default_config_path();
|
||||||
auto conf = std::make_unique<clrsync::core::io::toml_file>(config_path);
|
auto conf = std::make_unique<clrsync::core::io::toml_file>(config_path);
|
||||||
|
|
||||||
try
|
auto init_result = clrsync::core::config::instance().initialize(std::move(conf));
|
||||||
|
if (!init_result)
|
||||||
{
|
{
|
||||||
clrsync::core::config::instance().initialize(std::move(conf));
|
std::cerr << "Fatal error: " << init_result.error().description() << std::endl;
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "Fatal error: " << e.what() << std::endl;
|
|
||||||
std::cerr << "Hint: Set CLRSYNC_CONFIG_PATH environment variable or ensure config exists at: " << config_path << std::endl;
|
std::cerr << "Hint: Set CLRSYNC_CONFIG_PATH environment variable or ensure config exists at: " << config_path << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ palette_controller::palette_controller()
|
|||||||
|
|
||||||
if (m_palettes.empty())
|
if (m_palettes.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
auto default_theme = clrsync::core::config::instance().default_theme();
|
||||||
m_current_palette = m_palettes[clrsync::core::config::instance().default_theme()];
|
auto it = m_palettes.find(default_theme);
|
||||||
} catch (...) {
|
if (it != m_palettes.end()) {
|
||||||
|
m_current_palette = it->second;
|
||||||
|
} else {
|
||||||
m_current_palette = m_palettes.begin()->second;
|
m_current_palette = m_palettes.begin()->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +56,7 @@ void palette_controller::delete_current_palette()
|
|||||||
void palette_controller::apply_current_theme() const
|
void palette_controller::apply_current_theme() const
|
||||||
{
|
{
|
||||||
clrsync::core::theme_renderer<clrsync::core::io::toml_file> theme_renderer;
|
clrsync::core::theme_renderer<clrsync::core::io::toml_file> theme_renderer;
|
||||||
theme_renderer.apply_theme(m_current_palette.name());
|
(void)theme_renderer.apply_theme(m_current_palette.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void palette_controller::set_color(const std::string& key, const clrsync::core::color& color)
|
void palette_controller::set_color(const std::string& key, const clrsync::core::color& color)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "settings_window.hpp"
|
#include "settings_window.hpp"
|
||||||
#include "core/config/config.hpp"
|
#include "core/config/config.hpp"
|
||||||
|
#include "core/error.hpp"
|
||||||
#include "gui/font_loader.hpp"
|
#include "gui/font_loader.hpp"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -119,83 +120,85 @@ void settings_window::render()
|
|||||||
|
|
||||||
void settings_window::load_settings()
|
void settings_window::load_settings()
|
||||||
{
|
{
|
||||||
try
|
auto& cfg = clrsync::core::config::instance();
|
||||||
{
|
|
||||||
auto& cfg = clrsync::core::config::instance();
|
std::string default_theme = cfg.default_theme();
|
||||||
|
strncpy(m_default_theme, default_theme.c_str(), sizeof(m_default_theme) - 1);
|
||||||
std::string default_theme = cfg.default_theme();
|
m_default_theme[sizeof(m_default_theme) - 1] = '\0';
|
||||||
strncpy(m_default_theme, default_theme.c_str(), sizeof(m_default_theme) - 1);
|
|
||||||
m_default_theme[sizeof(m_default_theme) - 1] = '\0';
|
std::string palettes_path = cfg.palettes_path();
|
||||||
|
strncpy(m_palettes_path, palettes_path.c_str(), sizeof(m_palettes_path) - 1);
|
||||||
std::string palettes_path = cfg.palettes_path();
|
m_palettes_path[sizeof(m_palettes_path) - 1] = '\0';
|
||||||
strncpy(m_palettes_path, palettes_path.c_str(), sizeof(m_palettes_path) - 1);
|
|
||||||
m_palettes_path[sizeof(m_palettes_path) - 1] = '\0';
|
std::string font = cfg.font();
|
||||||
|
strncpy(m_font, font.c_str(), sizeof(m_font) - 1);
|
||||||
std::string font = cfg.font();
|
m_font[sizeof(m_font) - 1] = '\0';
|
||||||
strncpy(m_font, font.c_str(), sizeof(m_font) - 1);
|
|
||||||
m_font[sizeof(m_font) - 1] = '\0';
|
m_font_size = cfg.font_size();
|
||||||
|
|
||||||
m_font_size = cfg.font_size();
|
m_error_message = "";
|
||||||
|
|
||||||
m_error_message = "";
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
m_error_message = std::string("Failed to load settings: ") + e.what();
|
|
||||||
|
|
||||||
// Set defaults on error
|
|
||||||
strncpy(m_default_theme, "dark", sizeof(m_default_theme));
|
|
||||||
strncpy(m_palettes_path, "~/.config/clrsync/palettes", sizeof(m_palettes_path));
|
|
||||||
strncpy(m_font, "JetBrains Mono Nerd Font", sizeof(m_font));
|
|
||||||
m_font_size = 14;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void settings_window::apply_settings()
|
void settings_window::apply_settings()
|
||||||
{
|
{
|
||||||
try
|
auto& cfg = clrsync::core::config::instance();
|
||||||
|
|
||||||
|
if (strlen(m_default_theme) == 0)
|
||||||
{
|
{
|
||||||
auto& cfg = clrsync::core::config::instance();
|
m_error_message = "Default theme cannot be empty";
|
||||||
|
return;
|
||||||
if (strlen(m_default_theme) == 0)
|
|
||||||
{
|
|
||||||
m_error_message = "Default theme cannot be empty";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(m_palettes_path) == 0)
|
|
||||||
{
|
|
||||||
m_error_message = "Palettes path cannot be empty";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(m_font) == 0)
|
|
||||||
{
|
|
||||||
m_error_message = "Font cannot be empty";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_font_size < 8 || m_font_size > 48)
|
|
||||||
{
|
|
||||||
m_error_message = "Font size must be between 8 and 48";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.set_default_theme(m_default_theme);
|
|
||||||
cfg.set_palettes_path(m_palettes_path);
|
|
||||||
cfg.set_font(m_font);
|
|
||||||
cfg.set_font_size(m_font_size);
|
|
||||||
|
|
||||||
|
|
||||||
font_loader fn_loader;
|
|
||||||
auto font = fn_loader.load_font(m_font, m_font_size);
|
|
||||||
if (font)
|
|
||||||
ImGui::GetIO().FontDefault = font;
|
|
||||||
|
|
||||||
m_error_message = "";
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
|
||||||
|
if (strlen(m_palettes_path) == 0)
|
||||||
{
|
{
|
||||||
m_error_message = std::string("Failed to apply settings: ") + e.what();
|
m_error_message = "Palettes path cannot be empty";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strlen(m_font) == 0)
|
||||||
|
{
|
||||||
|
m_error_message = "Font cannot be empty";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_font_size < 8 || m_font_size > 48)
|
||||||
|
{
|
||||||
|
m_error_message = "Font size must be between 8 and 48";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result1 = cfg.set_default_theme(m_default_theme);
|
||||||
|
if (!result1)
|
||||||
|
{
|
||||||
|
m_error_message = "Failed to set default theme: " + result1.error().description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result2 = cfg.set_palettes_path(m_palettes_path);
|
||||||
|
if (!result2)
|
||||||
|
{
|
||||||
|
m_error_message = "Failed to set palettes path: " + result2.error().description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result3 = cfg.set_font(m_font);
|
||||||
|
if (!result3)
|
||||||
|
{
|
||||||
|
m_error_message = "Failed to set font: " + result3.error().description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result4 = cfg.set_font_size(m_font_size);
|
||||||
|
if (!result4)
|
||||||
|
{
|
||||||
|
m_error_message = "Failed to set font size: " + result4.error().description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
font_loader fn_loader;
|
||||||
|
auto font = fn_loader.load_font(m_font, m_font_size);
|
||||||
|
if (font)
|
||||||
|
ImGui::GetIO().FontDefault = font;
|
||||||
|
|
||||||
|
m_error_message = "";
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ void template_controller::set_template_enabled(const std::string& key, bool enab
|
|||||||
auto it = m_templates.find(key);
|
auto it = m_templates.find(key);
|
||||||
if (it != m_templates.end()) {
|
if (it != m_templates.end()) {
|
||||||
it->second.set_enabled(enabled);
|
it->second.set_enabled(enabled);
|
||||||
clrsync::core::config::instance().update_template(key, it->second);
|
(void)clrsync::core::config::instance().update_template(key, it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ void template_controller::set_template_output_path(const std::string& key, const
|
|||||||
auto it = m_templates.find(key);
|
auto it = m_templates.find(key);
|
||||||
if (it != m_templates.end()) {
|
if (it != m_templates.end()) {
|
||||||
it->second.set_output_path(path);
|
it->second.set_output_path(path);
|
||||||
clrsync::core::config::instance().update_template(key, it->second);
|
(void)clrsync::core::config::instance().update_template(key, it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ void template_controller::set_template_reload_command(const std::string& key, co
|
|||||||
auto it = m_templates.find(key);
|
auto it = m_templates.find(key);
|
||||||
if (it != m_templates.end()) {
|
if (it != m_templates.end()) {
|
||||||
it->second.set_reload_command(cmd);
|
it->second.set_reload_command(cmd);
|
||||||
clrsync::core::config::instance().update_template(key, it->second);
|
(void)clrsync::core::config::instance().update_template(key, it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -343,59 +343,62 @@ void template_editor::save_template()
|
|||||||
|
|
||||||
m_validation_error = "";
|
m_validation_error = "";
|
||||||
|
|
||||||
try
|
auto &cfg = clrsync::core::config::instance();
|
||||||
|
std::string palettes_path = cfg.palettes_path();
|
||||||
|
std::filesystem::path templates_dir =
|
||||||
|
std::filesystem::path(palettes_path).parent_path() / "templates";
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(templates_dir))
|
||||||
{
|
{
|
||||||
auto &cfg = clrsync::core::config::instance();
|
std::filesystem::create_directories(templates_dir);
|
||||||
std::string palettes_path = cfg.palettes_path();
|
}
|
||||||
std::filesystem::path templates_dir =
|
|
||||||
std::filesystem::path(palettes_path).parent_path() / "templates";
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(templates_dir))
|
std::filesystem::path template_file;
|
||||||
|
if (m_is_editing_existing)
|
||||||
|
{
|
||||||
|
auto existing_template_result = cfg.template_by_name(trimmed_name);
|
||||||
|
if (!existing_template_result)
|
||||||
{
|
{
|
||||||
std::filesystem::create_directories(templates_dir);
|
m_validation_error = "Template not found: " + existing_template_result.error().description();
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path template_file;
|
|
||||||
if (m_is_editing_existing)
|
|
||||||
{
|
|
||||||
const auto &existing_template = cfg.template_by_name(trimmed_name);
|
|
||||||
template_file = existing_template.template_path();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
template_file = templates_dir / trimmed_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string template_content = m_editor.GetText();
|
|
||||||
|
|
||||||
std::ofstream out(template_file);
|
|
||||||
if (!out.is_open())
|
|
||||||
{
|
|
||||||
m_validation_error = "Failed to write template file";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
template_file = existing_template_result.value()->template_path();
|
||||||
out << template_content;
|
|
||||||
out.close();
|
|
||||||
|
|
||||||
clrsync::core::theme_template tmpl(trimmed_name, template_file.string(), trimmed_path);
|
|
||||||
tmpl.set_reload_command(m_reload_command);
|
|
||||||
tmpl.set_enabled(m_enabled);
|
|
||||||
|
|
||||||
cfg.update_template(trimmed_name, tmpl);
|
|
||||||
|
|
||||||
m_template_name = trimmed_name;
|
|
||||||
m_output_path = trimmed_path;
|
|
||||||
m_is_editing_existing = true;
|
|
||||||
m_saved_content = m_editor.GetText();
|
|
||||||
m_has_unsaved_changes = false;
|
|
||||||
|
|
||||||
refresh_templates();
|
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
else
|
||||||
{
|
{
|
||||||
m_validation_error = std::string("Error saving template: ") + e.what();
|
template_file = templates_dir / trimmed_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string template_content = m_editor.GetText();
|
||||||
|
|
||||||
|
std::ofstream out(template_file);
|
||||||
|
if (!out.is_open())
|
||||||
|
{
|
||||||
|
m_validation_error = "Failed to write template file";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << template_content;
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
clrsync::core::theme_template tmpl(trimmed_name, template_file.string(), trimmed_path);
|
||||||
|
tmpl.set_reload_command(m_reload_command);
|
||||||
|
tmpl.set_enabled(m_enabled);
|
||||||
|
|
||||||
|
auto result = cfg.update_template(trimmed_name, tmpl);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
m_validation_error = "Error saving template: " + result.error().description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_template_name = trimmed_name;
|
||||||
|
m_output_path = trimmed_path;
|
||||||
|
m_is_editing_existing = true;
|
||||||
|
m_saved_content = m_editor.GetText();
|
||||||
|
m_has_unsaved_changes = false;
|
||||||
|
|
||||||
|
refresh_templates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_editor::load_template(const std::string &name)
|
void template_editor::load_template(const std::string &name)
|
||||||
@@ -413,27 +416,24 @@ void template_editor::load_template(const std::string &name)
|
|||||||
m_is_editing_existing = true;
|
m_is_editing_existing = true;
|
||||||
m_validation_error = "";
|
m_validation_error = "";
|
||||||
|
|
||||||
try
|
std::ifstream in(tmpl.template_path());
|
||||||
|
if (in.is_open())
|
||||||
{
|
{
|
||||||
std::ifstream in(tmpl.template_path());
|
std::string content;
|
||||||
if (in.is_open())
|
std::string line;
|
||||||
|
while (std::getline(in, line))
|
||||||
{
|
{
|
||||||
std::string content;
|
content += line + "\n";
|
||||||
std::string line;
|
|
||||||
while (std::getline(in, line))
|
|
||||||
{
|
|
||||||
content += line + "\n";
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
|
|
||||||
m_editor.SetText(content);
|
|
||||||
m_saved_content = content;
|
|
||||||
m_has_unsaved_changes = false;
|
|
||||||
}
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
m_editor.SetText(content);
|
||||||
|
m_saved_content = content;
|
||||||
|
m_has_unsaved_changes = false;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
else
|
||||||
{
|
{
|
||||||
m_validation_error = std::string("Error loading template: ") + e.what();
|
m_validation_error = "Error loading template: Failed to open file";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user