Compare commits
No commits in common. "48f25d4baa4b106342cbf681f14db8e3293682b7" and "7e4141b2825b98ea9bde2e6a963687e7afa7efda" have entirely different histories.
48f25d4baa
...
7e4141b282
|
@ -8,7 +8,7 @@ file(GLOB_RECURSE SOURCES_FILES src/*)
|
||||||
|
|
||||||
add_executable(clippy_terminal ${SOURCES_FILES})
|
add_executable(clippy_terminal ${SOURCES_FILES})
|
||||||
target_include_directories(clippy_terminal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(clippy_terminal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
target_link_libraries(clippy_terminal PRIVATE cppshell tmuxub rang jsoncons yaml-cpp)
|
target_link_libraries(clippy_terminal cppshell rang)
|
||||||
|
|
||||||
install(TARGETS clippy_terminal DESTINATION bin)
|
install(TARGETS clippy_terminal DESTINATION bin)
|
||||||
|
|
||||||
|
@ -20,31 +20,9 @@ FetchContent_Declare(
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(cppshell)
|
FetchContent_MakeAvailable(cppshell)
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
tmuxub
|
|
||||||
GIT_REPOSITORY https://gitlab.com/Onyad/tmuxub
|
|
||||||
GIT_TAG origin/main
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(tmuxub)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
rang
|
rang
|
||||||
GIT_REPOSITORY https://github.com/agauniyal/rang.git
|
GIT_REPOSITORY https://github.com/agauniyal/rang.git
|
||||||
GIT_TAG origin/master
|
GIT_TAG origin/master
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(rang)
|
FetchContent_MakeAvailable(rang)
|
||||||
|
|
||||||
set(JSONCONS_BUILD_TESTS OFF CACHE INTERNAL "Turn off tests")
|
|
||||||
FetchContent_Declare(
|
|
||||||
jsoncons
|
|
||||||
GIT_REPOSITORY https://github.com/danielaparker/jsoncons
|
|
||||||
GIT_TAG origin/master
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(jsoncons)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
yaml-cpp
|
|
||||||
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
|
|
||||||
GIT_TAG origin/master
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(yaml-cpp)
|
|
||||||
|
|
|
@ -25,13 +25,15 @@ void Clippy::Run(const std::vector<std::string>& args) {
|
||||||
for (size_t i = 1; i < args.size(); ++i) {
|
for (size_t i = 1; i < args.size(); ++i) {
|
||||||
std::cout << args[i] << (i + 1 == args.size() ? "" : ",") << " ";
|
std::cout << args[i] << (i + 1 == args.size() ? "" : ",") << " ";
|
||||||
}
|
}
|
||||||
std::cout << "}" << rang::bg::reset << rang::style::reset << std::endl;
|
std::cout << "}" << std::endl << rang::bg::reset << rang::style::reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clippy::TargetPtr Clippy::TryExecuteClippyCommand(const std::vector<std::string>& args) {
|
Clippy::TargetPtr Clippy::TryExecuteClippyCommand(
|
||||||
|
const std::vector<std::string>& args) {
|
||||||
using namespace utils::parametres;
|
using namespace utils::parametres;
|
||||||
using namespace clippy::targets;
|
using namespace clippy::targets;
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "help", Parameter::Anything)) {
|
if (CheckPatternParametres(args, Parameter::Skip, "help",
|
||||||
|
Parameter::Anything)) {
|
||||||
std::cout << "Hello I'm clippy" << std::endl;
|
std::cout << "Hello I'm clippy" << std::endl;
|
||||||
std::cout << "Parametres: { ";
|
std::cout << "Parametres: { ";
|
||||||
for (size_t i = 0; i < args.size(); ++i) {
|
for (size_t i = 0; i < args.size(); ++i) {
|
||||||
|
@ -39,12 +41,11 @@ Clippy::TargetPtr Clippy::TryExecuteClippyCommand(const std::vector<std::string>
|
||||||
}
|
}
|
||||||
std::cout << "}" << std::endl;
|
std::cout << "}" << std::endl;
|
||||||
|
|
||||||
std::cout << "You can use:\n cfg\n crt\n prj\n list\n setname\n loadcfg\n op" << std::endl;
|
|
||||||
|
|
||||||
return std::make_unique<EmptyTarget>();
|
return std::make_unique<EmptyTarget>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "cfg", Parameter::Anything)) {
|
if (CheckPatternParametres(args, Parameter::Skip, "cfg",
|
||||||
|
Parameter::Anything)) {
|
||||||
LoadProjects();
|
LoadProjects();
|
||||||
auto p = projects_->GetCurrentProject();
|
auto p = projects_->GetCurrentProject();
|
||||||
|
|
||||||
|
@ -55,44 +56,17 @@ Clippy::TargetPtr Clippy::TryExecuteClippyCommand(const std::vector<std::string>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "crt", Parameter::Anything)) {
|
if (CheckPatternParametres(args, Parameter::Skip, "crt",
|
||||||
|
Parameter::Anything)) {
|
||||||
LoadProjects();
|
LoadProjects();
|
||||||
return std::make_unique<CreateProjectConfig>(projects_.value());
|
return std::make_unique<CreateProjectConfig>(projects_.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "prj", Parameter::Anything)) {
|
|
||||||
// TODO description current project or project by name
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "list", Parameter::Nothing)) {
|
Clippy::TargetPtr Clippy::GetScriptTarget(
|
||||||
LoadProjects();
|
const std::vector<std::string>& args) {
|
||||||
|
|
||||||
return std::make_unique<PrintListProjects>(projects_.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "setname", Parameter::Anything)) {
|
|
||||||
LoadProjects();
|
|
||||||
|
|
||||||
return std::make_unique<SetNameProject>(projects_.value(), args[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "loadcfg", Parameter::Nothing)) {
|
|
||||||
LoadProjects();
|
|
||||||
|
|
||||||
return std::make_unique<OpenLoadConfig>(projects_.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckPatternParametres(args, Parameter::Skip, "op", Parameter::Anything)) {
|
|
||||||
LoadProjects();
|
|
||||||
|
|
||||||
return std::make_unique<OpenProject>(projects_.value(), args[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clippy::TargetPtr Clippy::GetScriptTarget(const std::vector<std::string>& args) {
|
|
||||||
LoadProjects();
|
LoadProjects();
|
||||||
auto p = projects_->GetCurrentProject();
|
auto p = projects_->GetCurrentProject();
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,11 @@ std::unique_ptr<clippy::targets::RunShellScript> Config::GetTarget(
|
||||||
std::vector<std::string> target_commands;
|
std::vector<std::string> target_commands;
|
||||||
target_commands.emplace_back("cd " + initial_directory_);
|
target_commands.emplace_back("cd " + initial_directory_);
|
||||||
|
|
||||||
bool target_exists = false;
|
bool target_begin = false;
|
||||||
bool in_target = false;
|
|
||||||
|
|
||||||
while (std::getline(in, current)) {
|
while (std::getline(in, current)) {
|
||||||
if (current == target + ":") {
|
if (current == target + ":") {
|
||||||
target_exists = true;
|
target_begin = true;
|
||||||
in_target = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,18 +37,18 @@ std::unique_ptr<clippy::targets::RunShellScript> Config::GetTarget(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::isspace(current[0])) {
|
if (!std::isspace(current[0]) && target_begin) {
|
||||||
in_target = false;
|
target_begin = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_target) {
|
if (target_begin) {
|
||||||
target_commands.emplace_back(Strip(std::move(current)));
|
target_commands.emplace_back(Strip(std::move(current)));
|
||||||
} else if (current[0] == '!') {
|
} else if (current[0] == '!') {
|
||||||
target_commands.emplace_back(current.substr(1, current.size() - 1));
|
target_commands.emplace_back(current.substr(1, current.size() - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target_exists) {
|
if (!target_begin) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,75 @@
|
||||||
#include <clippy/project_list.hpp>
|
#include <clippy/project_list.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
|
||||||
#include <sstream>
|
|
||||||
#include <utils/lock_file.hpp>
|
#include <utils/lock_file.hpp>
|
||||||
#include <utils/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include <utils/filesystem.hpp>
|
Config ProjectList::GetNewConfig(
|
||||||
|
const std::filesystem::path& config_directory) {
|
||||||
#include <jsoncons/json.hpp>
|
|
||||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
|
||||||
#include "yaml-cpp/node/parse.h"
|
|
||||||
|
|
||||||
#include <yaml-cpp/yaml.h>
|
|
||||||
|
|
||||||
Config ProjectList::GetNewConfig(const std::filesystem::path& config_directory) {
|
|
||||||
std::lock_guard guard(lock_file_);
|
std::lock_guard guard(lock_file_);
|
||||||
|
|
||||||
LoadWithoutLock();
|
LoadWithouLock();
|
||||||
|
|
||||||
auto path_to_config = utils::filesystem::GenerateFile(config_directory);
|
std::mt19937 rnd(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
|
|
||||||
|
auto RandomSymbol = [&rnd]() {
|
||||||
|
int n = rnd() % (26 + 26 + 10);
|
||||||
|
if (n < 26) {
|
||||||
|
return 'a' + n;
|
||||||
|
} else if (n < 26 + 26) {
|
||||||
|
return 'A' + n - 26;
|
||||||
|
} else {
|
||||||
|
return '0' + n - 26 - 26;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto GenerateFilename = [&rnd, &RandomSymbol]() {
|
||||||
|
std::string filename;
|
||||||
|
for (size_t i = 0; i < 6; ++i) {
|
||||||
|
filename += RandomSymbol();
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto filename = GenerateFilename();
|
||||||
|
while (true) {
|
||||||
|
bool exist_config = false;
|
||||||
|
for (auto& project : projects_) {
|
||||||
|
if (filename == project.configuration_file.filename()) {
|
||||||
|
exist_config = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!exist_config) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = GenerateFilename();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto path_to_config = config_directory / filename;
|
||||||
|
|
||||||
|
std::ofstream out(path_, std::ios::app);
|
||||||
|
out << std::filesystem::current_path() << " " << path_to_config << std::endl;
|
||||||
|
out.close();
|
||||||
|
|
||||||
projects_.emplace_back(std::filesystem::current_path(), path_to_config);
|
projects_.emplace_back(std::filesystem::current_path(), path_to_config);
|
||||||
|
|
||||||
SaveConfig();
|
|
||||||
|
|
||||||
return {path_to_config, std::filesystem::current_path()};
|
return {path_to_config, std::filesystem::current_path()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectList::Load() {
|
void ProjectList::Load() {
|
||||||
std::lock_guard guard(lock_file_);
|
std::lock_guard guard(lock_file_);
|
||||||
|
|
||||||
LoadWithoutLock();
|
LoadWithouLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectList::OldLoadConfig(const std::string& data) {
|
void ProjectList::LoadWithouLock() {
|
||||||
std::stringstream in(data);
|
std::ifstream in(path_);
|
||||||
|
|
||||||
Project current;
|
Project current;
|
||||||
|
|
||||||
|
@ -48,147 +78,15 @@ void ProjectList::OldLoadConfig(const std::string& data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename T>
|
std::optional<Project> ProjectList::GetCurrentProject() {
|
||||||
void UpdateField(jsoncons::json& data, const std::string& field, std::optional<T> member) {
|
|
||||||
if (member) {
|
|
||||||
data[field] = static_cast<U>(member.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename T>
|
|
||||||
void UpdateField(YAML::Node& data, const std::string& field, std::optional<T> member) {
|
|
||||||
if (member) {
|
|
||||||
data[field] = static_cast<U>(member.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectList::SaveConfig(tag_json) {
|
|
||||||
jsoncons::json result;
|
|
||||||
|
|
||||||
result["version"] = "0.1";
|
|
||||||
result["projects"] = std::vector<std::string>();
|
|
||||||
|
|
||||||
for (auto& project : projects_) {
|
|
||||||
jsoncons::json current;
|
|
||||||
current["path_to_config"] = std::string(project.configuration_file);
|
|
||||||
current["path_root_project"] = std::string(project.root_project);
|
|
||||||
|
|
||||||
UpdateField<std::string>(current, "name", project.name);
|
|
||||||
UpdateField<std::string>(current, "open_script", project.open_script);
|
|
||||||
|
|
||||||
result["projects"].emplace_back(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ofstream out(path_);
|
|
||||||
out << result.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectList::SaveConfig() {
|
|
||||||
YAML::Node result;
|
|
||||||
result["version"] = "0.2";
|
|
||||||
|
|
||||||
for (auto& project : projects_) {
|
|
||||||
YAML::Node current;
|
|
||||||
|
|
||||||
UpdateField<std::string>(current, "name", project.name);
|
|
||||||
current["path_root_project"] = std::string(project.root_project);
|
|
||||||
current["path_to_config"] = std::string(project.configuration_file);
|
|
||||||
UpdateField<std::string>(current, "open_script", project.open_script);
|
|
||||||
|
|
||||||
result["projects"].push_back(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ofstream out(path_);
|
|
||||||
out << result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::optional<T> GetOptionalField(const jsoncons::json& data, std::string field) {
|
|
||||||
return data.contains(field) ? std::make_optional(data[field].as<std::string>()) : std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::optional<T> GetOptionalField(const YAML::Node& data, std::string field) {
|
|
||||||
return data[field].IsDefined() ? std::make_optional(data[field].as<std::string>()) : std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectList::LoadConfig(const YAML::Node& data) {
|
|
||||||
if (data["version"].as<std::string>() != "0.2") {
|
|
||||||
throw std::logic_error("unsupport version");
|
|
||||||
}
|
|
||||||
|
|
||||||
Project current;
|
|
||||||
for (const auto& project : data["projects"]) {
|
|
||||||
current.configuration_file = project["path_to_config"].as<std::string>();
|
|
||||||
current.root_project = project["path_root_project"].as<std::string>();
|
|
||||||
|
|
||||||
current.name = GetOptionalField<std::string>(project, "name");
|
|
||||||
current.open_script = GetOptionalField<std::string>(project, "open_script");
|
|
||||||
|
|
||||||
projects_.emplace_back(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectList::LoadConfig(const jsoncons::json& data) {
|
|
||||||
if (data["version"] != "0.1") {
|
|
||||||
throw std::logic_error("unsupported version config");
|
|
||||||
}
|
|
||||||
|
|
||||||
Project current;
|
|
||||||
for (auto& project : data["projects"].array_range()) {
|
|
||||||
current.configuration_file = project["path_to_config"].as<std::string>();
|
|
||||||
current.root_project = project["path_root_project"].as<std::string>();
|
|
||||||
|
|
||||||
current.name = GetOptionalField<std::string>(project, "name");
|
|
||||||
current.open_script = GetOptionalField<std::string>(project, "open_script");
|
|
||||||
|
|
||||||
projects_.emplace_back(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectList::LoadWithoutLock() {
|
|
||||||
projects_.clear();
|
|
||||||
|
|
||||||
try {
|
|
||||||
LoadConfig(YAML::LoadFile(path_));
|
|
||||||
} catch (...) {
|
|
||||||
auto data = utils::filesystem::LoadFile(path_);
|
|
||||||
|
|
||||||
std::cout << "I can't parse yaml. Try read json?" << std::endl;
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
std::getline(std::cin, result);
|
|
||||||
|
|
||||||
if (result == "y") {
|
|
||||||
try {
|
|
||||||
LoadConfig(jsoncons::json::parse(data));
|
|
||||||
} catch (...) {
|
|
||||||
std::cout << "I can't read project lists. Try fix it?" << std::endl;
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
std::getline(std::cin, result);
|
|
||||||
|
|
||||||
if (result == "y") {
|
|
||||||
OldLoadConfig(data);
|
|
||||||
SaveConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SaveConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Project* ProjectList::GetCurrentProject_() {
|
|
||||||
auto current_path = std::filesystem::current_path();
|
auto current_path = std::filesystem::current_path();
|
||||||
|
|
||||||
Project* result = nullptr;
|
std::optional<Project> result;
|
||||||
auto UpdateResult = [&result](Project& p) {
|
auto UpdateResult = [&result](Project p) {
|
||||||
if (!result) {
|
if (!result.has_value()) {
|
||||||
result = &p;
|
result = p;
|
||||||
} else {
|
} else {
|
||||||
if (*result < p) {
|
result = std::max(p, result.value());
|
||||||
result = &p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,16 +108,3 @@ Project* ProjectList::GetCurrentProject_() {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Project* ProjectList::GetProjectByName_(const std::string& name) {
|
|
||||||
Project* result = nullptr;
|
|
||||||
for (auto& project : projects_) {
|
|
||||||
if (!project.name) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (project.name == name) {
|
|
||||||
result = &project;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <clippy/config.hpp>
|
#include <clippy/config.hpp>
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <utils/lock_file.hpp>
|
#include <utils/lock_file.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include <jsoncons/json.hpp>
|
|
||||||
#include <yaml-cpp/yaml.h>
|
|
||||||
#include "utils/config_path.hpp"
|
|
||||||
#include "utils/editor.hpp"
|
|
||||||
#include "utils/filesystem.hpp"
|
|
||||||
|
|
||||||
struct Project {
|
struct Project {
|
||||||
Project() {}
|
Project() {}
|
||||||
|
|
||||||
|
@ -23,14 +15,10 @@ struct Project {
|
||||||
|
|
||||||
std::strong_ordering operator<=>(const Project&) const = default;
|
std::strong_ordering operator<=>(const Project&) const = default;
|
||||||
|
|
||||||
Config GetConfig() {
|
Config GetConfig() { return Config{configuration_file, root_project}; }
|
||||||
return Config{configuration_file, root_project};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path root_project;
|
std::filesystem::path root_project;
|
||||||
std::filesystem::path configuration_file;
|
std::filesystem::path configuration_file;
|
||||||
std::optional<std::string> name;
|
|
||||||
std::optional<std::filesystem::path> open_script;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProjectList {
|
class ProjectList {
|
||||||
|
@ -41,72 +29,13 @@ class ProjectList {
|
||||||
|
|
||||||
Config GetNewConfig(const std::filesystem::path& config_directory);
|
Config GetNewConfig(const std::filesystem::path& config_directory);
|
||||||
|
|
||||||
const std::vector<Project>& GetProjects() const {
|
const std::vector<Project>& GetProjects() const { return projects_; }
|
||||||
return projects_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Project> GetCurrentProject() {
|
std::optional<Project> GetCurrentProject();
|
||||||
auto* p = GetCurrentProject_();
|
|
||||||
if (p) {
|
|
||||||
return *p;
|
|
||||||
} else {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNameCurrentProject(const std::string& name) {
|
|
||||||
auto* p = GetCurrentProject_();
|
|
||||||
if (p) {
|
|
||||||
p->name = name;
|
|
||||||
SaveConfig();
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Not exists current project");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path GetCurrentLoadConfig() {
|
|
||||||
auto* p = GetCurrentProject_();
|
|
||||||
if (p) {
|
|
||||||
if (p->open_script) {
|
|
||||||
return p->open_script.value();
|
|
||||||
} else {
|
|
||||||
auto scripts_path = utils::GetProjectDirectory() / "scripts";
|
|
||||||
{
|
|
||||||
std::lock_guard lock(lock_file_);
|
|
||||||
p->open_script = utils::filesystem::GenerateFile(scripts_path);
|
|
||||||
SaveConfig();
|
|
||||||
}
|
|
||||||
return p->open_script.value();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Not exists current project");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Project> GetProjectByName(const std::string& name) {
|
|
||||||
auto* p = GetProjectByName_(name);
|
|
||||||
if (p) {
|
|
||||||
return *p;
|
|
||||||
} else {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Project* GetCurrentProject_();
|
|
||||||
Project* GetProjectByName_(const std::string&);
|
|
||||||
|
|
||||||
void OldLoadConfig(const std::string&);
|
|
||||||
|
|
||||||
struct tag_json {};
|
|
||||||
void SaveConfig(tag_json);
|
|
||||||
|
|
||||||
void SaveConfig();
|
|
||||||
|
|
||||||
void Load();
|
void Load();
|
||||||
void LoadConfig(const jsoncons::json&);
|
void LoadWithouLock();
|
||||||
void LoadConfig(const YAML::Node&);
|
|
||||||
void LoadWithoutLock();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path path_;
|
std::filesystem::path path_;
|
||||||
|
|
|
@ -11,12 +11,8 @@
|
||||||
#include <rang.hpp>
|
#include <rang.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <deque>
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "utils/filesystem.hpp"
|
|
||||||
|
|
||||||
#include <tmuxub/tmuxub.hpp>
|
|
||||||
|
|
||||||
namespace clippy::targets {
|
namespace clippy::targets {
|
||||||
class Target {
|
class Target {
|
||||||
|
@ -35,9 +31,7 @@ class OpenProjectConfig : public Target {
|
||||||
public:
|
public:
|
||||||
OpenProjectConfig(Config config) : config_(config) {}
|
OpenProjectConfig(Config config) : config_(config) {}
|
||||||
|
|
||||||
void Execute() override {
|
void Execute() override { config_.Edit(); }
|
||||||
config_.Edit();
|
|
||||||
}
|
|
||||||
~OpenProjectConfig() override {}
|
~OpenProjectConfig() override {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -64,8 +58,7 @@ class CreateProjectConfig : public Target {
|
||||||
class RunShellScript : public Target {
|
class RunShellScript : public Target {
|
||||||
public:
|
public:
|
||||||
template <template <typename, typename...> class C, typename... Params>
|
template <template <typename, typename...> class C, typename... Params>
|
||||||
RunShellScript(const C<std::string, Params...>& commands)
|
RunShellScript(const C<std::string, Params...>& commands) : commands_(commands.begin(), commands.end()) {}
|
||||||
: commands_(commands.begin(), commands.end()) {}
|
|
||||||
|
|
||||||
void PushBack(const std::string& command) {
|
void PushBack(const std::string& command) {
|
||||||
commands_.push_back(command);
|
commands_.push_back(command);
|
||||||
|
@ -82,15 +75,16 @@ class RunShellScript : public Target {
|
||||||
cppshell::Shell s("bash", tmp_path);
|
cppshell::Shell s("bash", tmp_path);
|
||||||
|
|
||||||
for (auto& command : commands_) {
|
for (auto& command : commands_) {
|
||||||
std::cout << rang::fg::green << rang::style::bold << rang::bgB::blue << "->"
|
std::cout << rang::fg::green << rang::style::bold << rang::bgB::blue << "->" << rang::fg::reset
|
||||||
<< rang::fg::reset << rang::bg::reset << " " << command << rang::style::reset
|
<< rang::bg::reset << " " << command << rang::style::reset << std::endl;
|
||||||
<< std::endl;
|
|
||||||
s.Execute(command);
|
s.Execute(command);
|
||||||
if (int err = s.GetExitCodeLastCommand(); err != 0) {
|
if (int err = s.GetExitCodeLastCommand(); err != 0) {
|
||||||
std::cout << rang::fg::red << rang::style::bold << "Command exit with code " << err
|
std::cout << rang::fg::red << rang::style::bold
|
||||||
<< rang::fg::reset << rang::style::reset << std::endl;
|
<< "Command exit with code " << err << rang::fg::reset
|
||||||
std::cout << rang::fg::blue << rang::style::bold << "Continue execution? [Y/n] "
|
<< rang::style::reset << std::endl;
|
||||||
<< rang::fg::reset << rang::style::reset;
|
std::cout << rang::fg::blue << rang::style::bold
|
||||||
|
<< "Continue execution? [Y/n] " << rang::fg::reset
|
||||||
|
<< rang::style::reset;
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
std::getline(std::cin, result);
|
std::getline(std::cin, result);
|
||||||
|
@ -108,72 +102,4 @@ class RunShellScript : public Target {
|
||||||
private:
|
private:
|
||||||
std::deque<std::string> commands_;
|
std::deque<std::string> commands_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrintListProjects : public Target {
|
|
||||||
public:
|
|
||||||
PrintListProjects(ProjectList& projects) : projects_(projects) {}
|
|
||||||
|
|
||||||
void Execute() override {
|
|
||||||
for (auto& project : projects_.GetProjects()) {
|
|
||||||
std::cout << std::setw(10) << project.name.value_or("-") << " " << std::setw(50)
|
|
||||||
<< project.root_project << " " << std::setw(70) << project.configuration_file
|
|
||||||
<< std::setw(70) << project.open_script.value_or("-") << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProjectList& projects_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SetNameProject : public Target {
|
|
||||||
public:
|
|
||||||
SetNameProject(ProjectList& projects, std::string new_name)
|
|
||||||
: projects_(projects), new_name_(std::move(new_name)) {}
|
|
||||||
|
|
||||||
void Execute() override {
|
|
||||||
projects_.SetNameCurrentProject(new_name_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProjectList& projects_;
|
|
||||||
std::string new_name_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OpenLoadConfig : public Target {
|
|
||||||
public:
|
|
||||||
OpenLoadConfig(ProjectList& projects) : projects_(projects) {}
|
|
||||||
|
|
||||||
void Execute() override {
|
|
||||||
utils::OpenEditor(projects_.GetCurrentLoadConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProjectList& projects_;
|
|
||||||
std::string new_name_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OpenProject : public Target {
|
|
||||||
public:
|
|
||||||
OpenProject(ProjectList& projects, const std::string& name) : projects_(projects), name_(name) {}
|
|
||||||
|
|
||||||
void Execute() override {
|
|
||||||
auto p = projects_.GetProjectByName(name_);
|
|
||||||
|
|
||||||
tmuxub::Tmux t(utils::GetProjectDirectory() / "tmuxsocket");
|
|
||||||
if (t.HasSession(name_)) {
|
|
||||||
t.ConnectToSession(name_);
|
|
||||||
t.Exec();
|
|
||||||
} else {
|
|
||||||
auto file = utils::filesystem::LoadFile(p->open_script.value());
|
|
||||||
chdir(std::string(p.value().root_project).data());
|
|
||||||
t.CreateSession(name_);
|
|
||||||
t.SplitWindow(file);
|
|
||||||
t.Exec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProjectList& projects_;
|
|
||||||
std::string name_;
|
|
||||||
};
|
|
||||||
} // namespace clippy::targets
|
} // namespace clippy::targets
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
#include <utils/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <jsoncons/json.hpp>
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
std::signal(SIGPIPE, SIG_IGN);
|
std::signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
#include <random>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include <utils/random.hpp>
|
|
||||||
|
|
||||||
namespace utils::filesystem {
|
|
||||||
inline std::string LoadFile(const std::filesystem::path& file) {
|
|
||||||
std::ifstream in(file);
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
std::string tmp;
|
|
||||||
|
|
||||||
while (std::getline(in, tmp)) {
|
|
||||||
result += tmp;
|
|
||||||
result += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::filesystem::path GenerateFile(std::filesystem::path dir) {
|
|
||||||
if (!std::filesystem::is_directory(dir)) {
|
|
||||||
throw std::logic_error(std::string(dir) + " is not directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto RandomSymbol = []() {
|
|
||||||
int n = utils::random::RandInt(26 + 26 + 10);
|
|
||||||
if (n < 26) {
|
|
||||||
return 'a' + n;
|
|
||||||
} else if (n < 26 + 26) {
|
|
||||||
return 'A' + n - 26;
|
|
||||||
} else {
|
|
||||||
return '0' + n - 26 - 26;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto GenerateFilename = [length = 6]() mutable {
|
|
||||||
if (length > 10) {
|
|
||||||
throw std::logic_error("failed to create file");
|
|
||||||
}
|
|
||||||
std::string filename;
|
|
||||||
for (size_t i = 0; i < length; ++i) {
|
|
||||||
filename += RandomSymbol();
|
|
||||||
}
|
|
||||||
length++;
|
|
||||||
|
|
||||||
return filename;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto filename = GenerateFilename();
|
|
||||||
while (true) {
|
|
||||||
if (std::filesystem::status(dir / filename).type() == std::filesystem::file_type::not_found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = GenerateFilename();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir / filename;
|
|
||||||
}
|
|
||||||
} // namespace utils::filesystem
|
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <random>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
namespace utils::random {
|
|
||||||
static inline std::mt19937_64 rnd(std::chrono::system_clock::now().time_since_epoch().count());
|
|
||||||
|
|
||||||
inline uint64_t RandInt(uint64_t max_n) {
|
|
||||||
return rnd() % max_n;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue