Add config and command executor

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-10-22 11:27:13 +03:00
parent 237208d972
commit 8859504fed
7 changed files with 175 additions and 8 deletions

View File

@@ -91,6 +91,14 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(cpptrace)
FetchContent_Declare(
tomlplusplus
GIT_REPOSITORY https://github.com/marzer/tomlplusplus
GIT_TAG "v3.4.0"
GIT_SHALLOW 1
)
FetchContent_MakeAvailable(tomlplusplus)
add_subdirectory(vendor)
find_program(WAYLAND_SCANNER wayland-scanner REQUIRED)
@@ -189,6 +197,7 @@ add_custom_target(generate_protocols ALL
add_executable(waylight
${GEN_C_PRIVATES}
${CMAKE_CURRENT_SOURCE_DIR}/src/Config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/IconRegistry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Cache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/InotifyWatcher.cpp
@@ -215,6 +224,7 @@ target_link_libraries(waylight PRIVATE
PkgConfig::FONTCONFIG
PkgConfig::HARFBUZZ
tomlplusplus::tomlplusplus
cpptrace::cpptrace
tinyfiledialogs
mINI

View File

@@ -8,7 +8,9 @@
#include <cstdlib>
#include <cstring>
#include <poll.h>
#include <print>
#include <pthread.h>
#include <ranges>
#include <signal.h>
#include <span>
#include <sys/mman.h>
@@ -159,6 +161,25 @@ App::App()
std::filesystem::create_directories(m_data_home_dir);
}
{
auto const env = getenv("XDG_CONFIG_HOME");
if (env && *env) {
if (std::filesystem::exists(env)) {
m_config_home_dir = env;
}
}
if (m_config_home_dir.empty()) {
auto const home = getenv("HOME");
assert(home && *home);
m_config_home_dir = std::filesystem::path(home) / ".config";
std::filesystem::create_directories(m_config_home_dir);
}
m_config_home_dir /= "waylight";
std::filesystem::create_directories(m_config_home_dir);
m_config = Config::load(m_config_home_dir);
}
m_db = std::make_shared<SQLite::Database>(m_data_home_dir / "data.db",
SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
@@ -1243,4 +1264,65 @@ auto App::clipboard(std::string_view const &str) -> void
wl_display_flush(m_wayland.display);
}
void App::execute_command(bool terminal, std::string_view const command)
{
constexpr auto resolve_cmdline { [](std::string_view const cmdline,
std::vector<std::string> &out) {
std::ranges::copy(cmdline | std::views::split(' ')
| std::views::transform(
[](auto &&s) { return std::string(s.begin(), s.end()); }),
std::back_inserter(out));
} };
std::vector<std::string> args;
if (terminal) {
resolve_cmdline(m_config.terminal_cmdline, args);
} else {
args.push_back("/bin/sh");
args.push_back("-c");
}
args.push_back(std::string(command));
if (auto const &exe { args.at(0) }; exe.at(0) != '/') {
auto const *path_env { getenv("PATH") };
if (!(path_env && *path_env)) {
path_env = "/bin";
}
auto const path { std::string(path_env) };
for (auto const &dir :
path | std::views::split(':') | std::views::transform([](auto &&s) {
return std::filesystem::path(s.begin(), s.end());
}) | std::views::filter([](auto &&p) {
return std::filesystem::is_directory(p);
})) {
auto const path = dir / exe;
if (std::filesystem::is_regular_file(path)) {
args[0] = path.string();
}
}
}
std::print("Final args: ");
for (auto const &arg : args) {
std::print("{} ", arg);
}
std::println("");
std::vector<char const *> cargs;
std::transform(args.begin(), args.end(), std::back_inserter(cargs),
[](auto &&s) { return s.c_str(); });
cargs.push_back(nullptr);
auto cargsc { const_cast<char *const *>(cargs.data()) };
auto const pid = fork();
if (pid == 0) {
setsid();
execv(args.at(0).c_str(), cargsc);
} else if (pid < 0) {
throw std::runtime_error("Failed to fork process");
}
}
} // namespace Waylight

View File

@@ -24,6 +24,7 @@ extern "C" {
#include <xkbcommon/xkbcommon.h>
#include "Cache.hpp"
#include "Config.hpp"
#include "IconRegistry.hpp"
#include "ImGui.hpp"
#include "TextRenderer.hpp"
@@ -201,9 +202,6 @@ private:
bool surrounding_dirty { false };
} m_ime;
// NOTE: Canonicalize first!
std::unordered_map<std::filesystem::path, Texture2D> m_textures;
auto get_texture(std::filesystem::path const &path) -> Texture2D const &
{
if (m_textures.contains(path)) {
@@ -218,10 +216,16 @@ private:
return m_textures[path];
}
void execute_command(bool terminal, std::string_view const command);
// NOTE: Canonicalize first!
std::unordered_map<std::filesystem::path, Texture2D> m_textures;
enum_array<Theme, ColorScheme> m_themes { make_default_themes() };
Theme m_active_theme { Theme::Light };
IconRegistry m_ir;
std::optional<Cache> m_cache;
Config m_config;
int m_win_w { 800 };
int m_win_h { 600 };
@@ -231,6 +235,7 @@ private:
Color m_accent_color { 127, 127, 255, 255 };
std::filesystem::path m_data_home_dir {};
std::filesystem::path m_config_home_dir {};
std::shared_ptr<SQLite::Database> m_db {};
int m_sfd { -1 };
};

47
src/Config.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "Config.hpp"
#include <filesystem>
#include <fstream>
#include <print>
#include <toml++/toml.hpp>
namespace Waylight {
void Config::write(std::filesystem::path const &path)
{
std::ofstream f(path);
if (!f) {
throw std::runtime_error("Failed to open config file for writing");
}
std::println(f, "[settings]");
std::println(f, "terminal_cmdline=\"{}\"", terminal_cmdline);
}
auto Config::load(std::filesystem::path const &config_dir_path) -> Config const
{
if (!std::filesystem::is_directory(config_dir_path))
throw std::runtime_error("Provided path is not a directory!");
Config cfg {};
std::filesystem::path path_config { config_dir_path / "config.toml" };
if (!std::filesystem::is_regular_file(path_config)) {
try {
std::filesystem::remove_all(path_config);
} catch (std::exception const &e) {
}
cfg.write(path_config);
}
std::println("Config file: {}", path_config.string());
auto const tbl { toml::parse_file(path_config.string()) };
auto const terminal_cmdline { tbl["settings"]["terminal_cmdline"].value_or(
"kitty -c") };
cfg.terminal_cmdline = terminal_cmdline;
return cfg;
}
} // namespace Waylight

17
src/Config.hpp Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include <filesystem>
#include <string>
namespace Waylight {
struct Config {
std::string terminal_cmdline { "kitty" };
void write(std::filesystem::path const &path);
static auto load(std::filesystem::path const &config_dir_path)
-> Config const;
};
} // namespace Waylight

View File

@@ -66,6 +66,12 @@ auto App::tick() -> void
result.test(1)) {
m_ime.surrounding_dirty = true;
} else if (result.test(0)) {
if (text_input_data == "kitty") {
execute_command(false, "kitty");
} else if (text_input_data == "nvim") {
execute_command(true, "nvim");
}
text_input_data = "";
}