From a037cc4ef7f389c07f86aca5d3b4b9149b4b774e Mon Sep 17 00:00:00 2001 From: Slackadays Date: Sat, 9 Nov 2024 20:14:17 -0500 Subject: [PATCH] Finish Script action, add justfile --- justfile | 14 +++++++++ src/cb/src/actions/info.cpp | 25 +++++++++++++-- src/cb/src/actions/script.cpp | 56 ++++++++++++++++++++++++++++++--- src/cb/src/clipboard.cpp | 1 + src/cb/src/clipboard.hpp | 7 ++++- src/cb/src/main.cpp | 2 ++ src/cb/src/utils/files.cpp | 11 ++++--- src/cb/src/utils/formatting.cpp | 2 +- src/cb/src/utils/utils.cpp | 6 +++- 9 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 justfile diff --git a/justfile b/justfile new file mode 100644 index 000000000..4c4e89584 --- /dev/null +++ b/justfile @@ -0,0 +1,14 @@ +default: + @just --list + +build: + if [ ! -d "build" ]; then mkdir build; fi + + cd build; cmake .. -DCMAKE_BUILD_TYPE=Release + + cd build; cmake --build . -j 12 + + cd build; sudo cmake --install . + +clean: + if [ -d "build" ]; then rm -rf build; fi \ No newline at end of file diff --git a/src/cb/src/actions/info.cpp b/src/cb/src/actions/info.cpp index 3878071bc..5b9c1c51f 100644 --- a/src/cb/src/actions/info.cpp +++ b/src/cb/src/actions/info.cpp @@ -143,9 +143,30 @@ void info() { if (fs::exists(path.metadata.script)) { auto script = fileContents(path.metadata.script).value(); if (script.size() > 50) { - fprintf(stderr, formatColors("[info]%s┃ Script: [help]%s...[blank]\n").data(), endbar, makeControlCharactersVisible(removeExcessWhitespace(script.substr(0, 50))).data()); + fprintf(stderr, formatColors("[info]%s┃ Script preview: [help]%s...[blank]\n").data(), endbar, makeControlCharactersVisible(removeExcessWhitespace(script.substr(0, 50))).data()); } else { - fprintf(stderr, formatColors("[info]%s┃ Script: [help]%s[blank]\n").data(), endbar, makeControlCharactersVisible(removeExcessWhitespace(script)).data()); + fprintf(stderr, formatColors("[info]%s┃ Script preview: [help]%s[blank]\n").data(), endbar, makeControlCharactersVisible(removeExcessWhitespace(script)).data()); + } + auto lines = fileLines(path.metadata.script_config, true); + if (lines[0] != "") { + fprintf(stderr, formatColors("[info]%s┃ Script actions: [help]").data(), endbar); + for (const auto& action : regexSplit(lines[0], std::regex(" "))) { + fprintf(stderr, "%s", action.data()); + if (action != regexSplit(lines[0], std::regex(" ")).back()) fprintf(stderr, ", "); + } + fprintf(stderr, "%s", formatColors("[blank]\n").data()); + } else { + fprintf(stderr, formatColors("[info]%s┃ This script is set to run for all actions.[blank]\n").data(), endbar); + } + if (lines.size() > 1 && lines[1] != "") { + fprintf(stderr, formatColors("[info]%s┃ Script timings: [help]").data(), endbar); + for (const auto& timing : regexSplit(lines[1], std::regex(" "))) { + fprintf(stderr, "%s", timing.data()); + if (timing != regexSplit(lines[1], std::regex(" ")).back()) fprintf(stderr, ", "); + } + fprintf(stderr, "%s", formatColors("[blank]\n").data()); + } else { + fprintf(stderr, formatColors("[info]%s┃ This script is set to run before and after all actions.[blank]\n").data(), endbar); } } else { fprintf(stderr, formatColors("[info]%s┃ There is no script for this clipboard.[blank]\n").data(), endbar); diff --git a/src/cb/src/actions/script.cpp b/src/cb/src/actions/script.cpp index 7fc1a6449..de9a78df7 100644 --- a/src/cb/src/actions/script.cpp +++ b/src/cb/src/actions/script.cpp @@ -18,8 +18,23 @@ #include #endif +bool runForThisAction = true; +bool runBefore = true; +bool runAfter = true; + namespace PerformAction { void script() { + std::string dataToWrite; + for (const auto& action : script_actions) { + dataToWrite += action + " "; + } + if (dataToWrite.back() == ' ') dataToWrite.back() = '\n'; else dataToWrite += '\n'; + for (const auto& timing : script_timings) { + dataToWrite += timing + " "; + } + if (dataToWrite.back() == ' ') dataToWrite.back() = '\n'; else dataToWrite += '\n'; + writeToFile(path.metadata.script_config, dataToWrite); + checkClipboardScriptEligibility(); if (io_type == IOType::File) { if (copying.items.size() > 1) { error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] You can only set one script file to run. [help]⬤ Try providing a single script file instead.[blank]\n")); @@ -45,6 +60,7 @@ void script() { fs::remove(path.metadata.script); fs::copy(copying.items.at(0), path.metadata.script); fs::permissions(path.metadata.script, fs::perms::owner_exec, fs::perm_options::add); + if (output_silent || confirmation_silent) return; stopIndicator(); fprintf(stderr, formatColors("[success][inverse] ✔ [noinverse] Saved script \"%s\"[blank]\n").data(), fileContents(path.metadata.script).value().data()); @@ -72,6 +88,10 @@ void script() { } // namespace PerformAction void runClipboardScript() { + //std::cout << "Run for this action: " << runForThisAction << std::endl; + //std::cout << "Run before: " << runBefore << std::endl; + //std::cout << "Run after: " << runAfter << std::endl; + if (!fs::is_regular_file(path.metadata.script)) return; #if defined(_WIN32) || defined(_WIN64) @@ -101,13 +121,39 @@ void runClipboardScript() { } }; - if (!secondRun) - execute("before"); - else - execute("after"); + if (runForThisAction) { + if (!secondRun && runBefore) { + execute("before"); + } else if (secondRun && runAfter) { + execute("after"); + } + } fs::current_path(currentPath); secondRun = true; #endif -} \ No newline at end of file +} + +void checkClipboardScriptEligibility() { + if (!fs::is_regular_file(path.metadata.script_config)) return; + + auto lines = fileLines(path.metadata.script_config, true); + + if (lines.empty()) return; + + auto scriptActions = regexSplit(lines[0], std::regex(" ")); + + if (!scriptActions.empty() && scriptActions.back() != "") { + runForThisAction = (std::find(scriptActions.begin(), scriptActions.end(), actions[action]) != scriptActions.end()) || (std::find(scriptActions.begin(), scriptActions.end(), action_shortcuts[action]) != scriptActions.end()); + } + + if (lines.size() < 2) return; + + auto scriptTimings = regexSplit(lines[1], std::regex(" ")); + + if (!scriptTimings.empty() && scriptTimings.back() != "") { + runBefore = std::find(scriptTimings.begin(), scriptTimings.end(), "before") != scriptTimings.end(); + runAfter = std::find(scriptTimings.begin(), scriptTimings.end(), "after") != scriptTimings.end(); + } +} diff --git a/src/cb/src/clipboard.cpp b/src/cb/src/clipboard.cpp index c278e7fc0..80dda4a36 100644 --- a/src/cb/src/clipboard.cpp +++ b/src/cb/src/clipboard.cpp @@ -48,6 +48,7 @@ Clipboard::Clipboard(const std::string& clipboard_name, const unsigned long& cli metadata.notes = metadata / constants.notes_name; metadata.originals = metadata / constants.original_files_name; metadata.script = metadata / constants.script_name; + metadata.script_config = metadata / constants.script_config_name; metadata.version = metadata / constants.storage_protocol_version_name; fs::create_directories(data); diff --git a/src/cb/src/clipboard.hpp b/src/cb/src/clipboard.hpp index 08997a411..276d5ac29 100644 --- a/src/cb/src/clipboard.hpp +++ b/src/cb/src/clipboard.hpp @@ -91,6 +91,7 @@ struct Constants { std::string_view ignore_secret_name = "ignore.secret"; std::string_view lock_name = "lock"; std::string_view script_name = "script"; + std::string_view script_config_name = "script.config"; std::string_view data_directory = "data"; std::string_view metadata_directory = "metadata"; std::string_view import_export_directory = "Exported_Clipboards"; @@ -144,7 +145,7 @@ static auto thisPID() { } std::optional fileContents(const fs::path& path); -std::vector fileLines(const fs::path& path); +std::vector fileLines(const fs::path& path, bool includeEmptyLines = false); bool stopIndicator(bool change_condition_variable = true); @@ -176,6 +177,8 @@ extern bool secret_selection; extern std::string preferred_mime; extern std::vector available_mimes; +extern std::vector script_actions; +extern std::vector script_timings; enum class ClipboardState : int { Setup, @@ -318,6 +321,7 @@ class Clipboard { fs::path notes; fs::path originals; fs::path script; + fs::path script_config; fs::path version; operator fs::path() { return root; } operator fs::path() const { return root; } @@ -463,6 +467,7 @@ void setTheme(const std::string_view& theme); size_t totalDirectorySize(const fs::path& directory); size_t directoryOverhead(const fs::path& directory); void runClipboardScript(); +void checkClipboardScriptEligibility(); extern Message help_message; extern Message check_clipboard_status_message; diff --git a/src/cb/src/main.cpp b/src/cb/src/main.cpp index 36b27ee8d..07a31f313 100644 --- a/src/cb/src/main.cpp +++ b/src/cb/src/main.cpp @@ -70,6 +70,8 @@ int main(int argc, char* argv[]) { checkItemSize(totalItemSize()); + checkClipboardScriptEligibility(); + runClipboardScript(); performAction(); diff --git a/src/cb/src/utils/files.cpp b/src/cb/src/utils/files.cpp index 555d96000..72f47191a 100644 --- a/src/cb/src/utils/files.cpp +++ b/src/cb/src/utils/files.cpp @@ -51,12 +51,13 @@ std::optional fileContents(const fs::path& path) { #endif } -std::vector fileLines(const fs::path& path) { +std::vector fileLines(const fs::path& path, bool includeEmptyLines) { std::vector lines; - std::ifstream input_file(path, std::ios::binary); - for (std::string line; !input_file.eof();) { - std::getline(input_file, line); - if (!line.empty()) lines.emplace_back(line); + auto content = fileContents(path); + if (!content) return lines; + std::istringstream stream(*content); + for (std::string line; std::getline(stream, line);) { + if (!line.empty() || includeEmptyLines) lines.emplace_back(line); } return lines; } diff --git a/src/cb/src/utils/formatting.cpp b/src/cb/src/utils/formatting.cpp index 60f80622b..0bf5af387 100644 --- a/src/cb/src/utils/formatting.cpp +++ b/src/cb/src/utils/formatting.cpp @@ -72,7 +72,7 @@ std::string makeControlCharactersVisible(const std::string_view& oldStr, size_t const std::array, 8> replacementCharacters { {{'\n', "\\n"}, {'\r', "\\r"}, {'\a', "\\a"}, {'\b', "\\b"}, {'\f', "\\f"}, {'\t', "\\t"}, {'\v', "\\v"}, {'\0', "\\0"}}}; - for (size_t i = 0; i < len - 1 && i < oldStr.size(); i++) { + for (size_t i = 0; i < len && i < oldStr.size(); i++) { bool matched = false; for (const auto& [character, replacement] : replacementCharacters) { if (oldStr[i] == character) { diff --git a/src/cb/src/utils/utils.cpp b/src/cb/src/utils/utils.cpp index fe5c155b5..3d93c4c56 100644 --- a/src/cb/src/utils/utils.cpp +++ b/src/cb/src/utils/utils.cpp @@ -58,6 +58,8 @@ std::string maximumHistorySize; std::string preferred_mime; std::vector available_mimes; +std::vector script_actions; +std::vector script_timings; std::vector arguments; @@ -468,6 +470,8 @@ void setFlags() { if (flagIsPresent("--fast-copy") || flagIsPresent("-fc")) copying.use_safe_copy = false; if (auto flag = flagIsPresent("--mime"); flag != "") preferred_mime = flag; if (auto flag = flagIsPresent("-m"); flag != "") preferred_mime = flag; + if (auto flag = flagIsPresent("--actions"); flag != "") script_actions = regexSplit(flag, std::regex(",")); + if (auto flag = flagIsPresent("--timings"); flag != "") script_timings = regexSplit(flag, std::regex(",")); if (flagIsPresent("--no-progress") || flagIsPresent("-np")) progress_silent = true; if (flagIsPresent("--no-confirmation") || flagIsPresent("-nc")) confirmation_silent = true; if (flagIsPresent("--secret") || flagIsPresent("-s")) secret_selection = true; @@ -769,4 +773,4 @@ void showSuccesses() { else if ((successes.files > 1) && (successes.directories > 1)) fprintf(stderr, many_files_many_directories_success_message().data(), did_action[action].data(), successes.files.load(), successes.directories.load()); } -} +} \ No newline at end of file