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_MakeAvailable(SQLiteCpp)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
cpptrace
|
cpptrace
|
||||||
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
|
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
|
||||||
GIT_TAG "v1.0.1"
|
GIT_TAG "v1.0.1"
|
||||||
GIT_SHALLOW 1
|
GIT_SHALLOW 1
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(cpptrace)
|
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)
|
add_subdirectory(vendor)
|
||||||
|
|
||||||
find_program(WAYLAND_SCANNER wayland-scanner REQUIRED)
|
find_program(WAYLAND_SCANNER wayland-scanner REQUIRED)
|
||||||
@@ -189,6 +197,7 @@ add_custom_target(generate_protocols ALL
|
|||||||
add_executable(waylight
|
add_executable(waylight
|
||||||
${GEN_C_PRIVATES}
|
${GEN_C_PRIVATES}
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Config.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/IconRegistry.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/IconRegistry.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Cache.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Cache.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/InotifyWatcher.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/InotifyWatcher.cpp
|
||||||
@@ -215,6 +224,7 @@ target_link_libraries(waylight PRIVATE
|
|||||||
PkgConfig::FONTCONFIG
|
PkgConfig::FONTCONFIG
|
||||||
PkgConfig::HARFBUZZ
|
PkgConfig::HARFBUZZ
|
||||||
|
|
||||||
|
tomlplusplus::tomlplusplus
|
||||||
cpptrace::cpptrace
|
cpptrace::cpptrace
|
||||||
tinyfiledialogs
|
tinyfiledialogs
|
||||||
mINI
|
mINI
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
fontconfig
|
fontconfig
|
||||||
harfbuzz
|
harfbuzz
|
||||||
sqlite
|
sqlite
|
||||||
zenity
|
zenity
|
||||||
boost
|
boost
|
||||||
];
|
];
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
cmake
|
cmake
|
||||||
|
|||||||
82
src/App.cpp
82
src/App.cpp
@@ -8,7 +8,9 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <print>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <ranges>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@@ -159,6 +161,25 @@ App::App()
|
|||||||
std::filesystem::create_directories(m_data_home_dir);
|
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",
|
m_db = std::make_shared<SQLite::Database>(m_data_home_dir / "data.db",
|
||||||
SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
|
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);
|
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
|
} // namespace Waylight
|
||||||
|
|||||||
11
src/App.hpp
11
src/App.hpp
@@ -24,6 +24,7 @@ extern "C" {
|
|||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#include "Cache.hpp"
|
#include "Cache.hpp"
|
||||||
|
#include "Config.hpp"
|
||||||
#include "IconRegistry.hpp"
|
#include "IconRegistry.hpp"
|
||||||
#include "ImGui.hpp"
|
#include "ImGui.hpp"
|
||||||
#include "TextRenderer.hpp"
|
#include "TextRenderer.hpp"
|
||||||
@@ -201,9 +202,6 @@ private:
|
|||||||
bool surrounding_dirty { false };
|
bool surrounding_dirty { false };
|
||||||
} m_ime;
|
} m_ime;
|
||||||
|
|
||||||
// NOTE: Canonicalize first!
|
|
||||||
std::unordered_map<std::filesystem::path, Texture2D> m_textures;
|
|
||||||
|
|
||||||
auto get_texture(std::filesystem::path const &path) -> Texture2D const &
|
auto get_texture(std::filesystem::path const &path) -> Texture2D const &
|
||||||
{
|
{
|
||||||
if (m_textures.contains(path)) {
|
if (m_textures.contains(path)) {
|
||||||
@@ -218,10 +216,16 @@ private:
|
|||||||
return m_textures[path];
|
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() };
|
enum_array<Theme, ColorScheme> m_themes { make_default_themes() };
|
||||||
Theme m_active_theme { Theme::Light };
|
Theme m_active_theme { Theme::Light };
|
||||||
IconRegistry m_ir;
|
IconRegistry m_ir;
|
||||||
std::optional<Cache> m_cache;
|
std::optional<Cache> m_cache;
|
||||||
|
Config m_config;
|
||||||
|
|
||||||
int m_win_w { 800 };
|
int m_win_w { 800 };
|
||||||
int m_win_h { 600 };
|
int m_win_h { 600 };
|
||||||
@@ -231,6 +235,7 @@ private:
|
|||||||
Color m_accent_color { 127, 127, 255, 255 };
|
Color m_accent_color { 127, 127, 255, 255 };
|
||||||
|
|
||||||
std::filesystem::path m_data_home_dir {};
|
std::filesystem::path m_data_home_dir {};
|
||||||
|
std::filesystem::path m_config_home_dir {};
|
||||||
std::shared_ptr<SQLite::Database> m_db {};
|
std::shared_ptr<SQLite::Database> m_db {};
|
||||||
int m_sfd { -1 };
|
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)) {
|
result.test(1)) {
|
||||||
m_ime.surrounding_dirty = true;
|
m_ime.surrounding_dirty = true;
|
||||||
} else if (result.test(0)) {
|
} 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 = "";
|
text_input_data = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user