Add config and command executor
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
@@ -84,13 +84,21 @@ FetchContent_Declare(
|
||||
FetchContent_MakeAvailable(SQLiteCpp)
|
||||
|
||||
FetchContent_Declare(
|
||||
cpptrace
|
||||
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
|
||||
GIT_TAG "v1.0.1"
|
||||
cpptrace
|
||||
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
|
||||
GIT_TAG "v1.0.1"
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
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
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
fontconfig
|
||||
harfbuzz
|
||||
sqlite
|
||||
zenity
|
||||
boost
|
||||
zenity
|
||||
boost
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
cmake
|
||||
|
||||
82
src/App.cpp
82
src/App.cpp
@@ -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
|
||||
|
||||
11
src/App.hpp
11
src/App.hpp
@@ -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
47
src/Config.cpp
Normal 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
17
src/Config.hpp
Normal 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
|
||||
@@ -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 = "";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user