diff --git a/documentation/manpages/man.1 b/documentation/manpages/man.1 index 220b8095c..06c5c5038 100644 --- a/documentation/manpages/man.1 +++ b/documentation/manpages/man.1 @@ -151,4 +151,4 @@ Report all bugs to \f[B]https://github.com/Slackadays/Clipboard\f[R] or \f[B]https://discord.gg/J6asnc3pEG\f[R]. .SS COPYRIGHT .PP -Copyright (c) 2023 Jackson Huff. +Copyright (c) 2022-2024 Jackson Huff. diff --git a/documentation/manpages/man.md b/documentation/manpages/man.md index 01ccebdfe..9d940475d 100644 --- a/documentation/manpages/man.md +++ b/documentation/manpages/man.md @@ -153,4 +153,4 @@ Report all bugs to __https://github.com/Slackadays/Clipboard__ or __https://disc ## COPYRIGHT -Copyright (c) 2023 Jackson Huff. \ No newline at end of file +Copyright (c) 2022-2024 Jackson Huff. \ No newline at end of file diff --git a/src/cb/CMakeLists.txt b/src/cb/CMakeLists.txt index 102392e50..e97548872 100644 --- a/src/cb/CMakeLists.txt +++ b/src/cb/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable(cb src/utils/files.cpp src/utils/distance.cpp src/utils/directorysize.cpp + src/utils/cowcopy.cpp ) enable_lto(cb) diff --git a/src/cb/src/actions/info.cpp b/src/cb/src/actions/info.cpp index 029feb1b7..3878071bc 100644 --- a/src/cb/src/actions/info.cpp +++ b/src/cb/src/actions/info.cpp @@ -39,13 +39,16 @@ void info() { fprintf(stderr, "━"); fprintf(stderr, "%s", formatColors("┓[blank]\n").data()); + auto endbarStr = generatedEndbar(); + auto endbar = endbarStr.data(); + // creation date #if defined(UNIX_OR_UNIX_LIKE) struct stat info; stat(path.string().data(), &info); std::string time(std::ctime(&info.st_ctime)); std::erase(time, '\n'); - fprintf(stderr, formatColors("[info]%s┃ Created [help]%s[blank]\n").data(), generatedEndbar().data(), time.data()); + fprintf(stderr, formatColors("[info]%s┃ Created [help]%s[blank]\n").data(), endbar, time.data()); #elif defined(_WIN32) || defined(_WIN64) fprintf(stderr, formatColors("[info]┃ Created [help]n/a[blank]\n").data()); #endif @@ -59,67 +62,67 @@ void info() { } time = std::ctime(&latest); std::erase(time, '\n'); - fprintf(stderr, formatColors("[info]%s┃ Content last changed [help]%s[blank]\n").data(), generatedEndbar().data(), time.data()); + fprintf(stderr, formatColors("[info]%s┃ Content last changed [help]%s[blank]\n").data(), endbar, time.data()); #elif defined(_WIN32) || defined(_WIN64) fprintf(stderr, formatColors("[info]┃ Content last changed [help]%s[blank]\n").data(), std::format("{}", fs::last_write_time(path)).data()); #endif - fprintf(stderr, formatColors("[info]%s┃ Stored in [help]%s[blank]\n").data(), generatedEndbar().data(), path.string().data()); + fprintf(stderr, formatColors("[info]%s┃ Stored in [help]%s[blank]\n").data(), endbar, path.string().data()); #if defined(UNIX_OR_UNIX_LIKE) struct passwd* pw = getpwuid(info.st_uid); - fprintf(stderr, formatColors("[info]%s┃ Owned by [help]%s[blank]\n").data(), generatedEndbar().data(), pw->pw_name); + fprintf(stderr, formatColors("[info]%s┃ Owned by [help]%s[blank]\n").data(), endbar, pw->pw_name); #elif defined(_WIN32) || defined(_WIN64) fprintf(stderr, formatColors("[info]┃ Owned by [help]n/a[blank]\n").data()); #endif - fprintf(stderr, formatColors("[info]%s┃ Persistent? [help]%s[blank]\n").data(), generatedEndbar().data(), path.is_persistent ? "Yes" : "No"); + fprintf(stderr, formatColors("[info]%s┃ Persistent? [help]%s[blank]\n").data(), endbar, path.is_persistent ? "Yes" : "No"); auto totalEntries = path.totalEntries(); auto totalSize = totalDirectorySize(path); auto spaceAvailable = fs::space(path).available; - fprintf(stderr, formatColors("[info]%s┃ Total entries: [help]%zu[blank]\n").data(), generatedEndbar().data(), totalEntries); - fprintf(stderr, formatColors("[info]%s┃ Total clipboard size: [help]%s[blank]\n").data(), generatedEndbar().data(), formatBytes(totalSize).data()); - fprintf(stderr, formatColors("[info]%s┃ Total space remaining: [help]%s[blank]\n").data(), generatedEndbar().data(), formatBytes(spaceAvailable).data()); - fprintf(stderr, formatColors("[info]%s┃ Approx. entries remaining: [help]%s[blank]\n").data(), generatedEndbar().data(), formatNumbers(spaceAvailable / (totalSize / totalEntries)).data()); + fprintf(stderr, formatColors("[info]%s┃ Total entries: [help]%zu[blank]\n").data(), endbar, totalEntries); + fprintf(stderr, formatColors("[info]%s┃ Total clipboard size: [help]%s[blank]\n").data(), endbar, formatBytes(totalSize).data()); + fprintf(stderr, formatColors("[info]%s┃ Total space remaining: [help]%s[blank]\n").data(), endbar, formatBytes(spaceAvailable).data()); + fprintf(stderr, formatColors("[info]%s┃ Approx. entries remaining: [help]%s[blank]\n").data(), endbar, formatNumbers(spaceAvailable / (totalSize / totalEntries)).data()); if (path.holdsRawDataInCurrentEntry()) { - fprintf(stderr, formatColors("[info]%s┃ Content size: [help]%s[blank]\n").data(), generatedEndbar().data(), formatBytes(fs::file_size(path.data.raw)).data()); - fprintf(stderr, formatColors("[info]%s┃ Content type: [help]%s[blank]\n").data(), generatedEndbar().data(), inferMIMEType(fileContents(path.data.raw).value()).value_or("text/plain").data()); + fprintf(stderr, formatColors("[info]%s┃ Content size: [help]%s[blank]\n").data(), endbar, formatBytes(fs::file_size(path.data.raw)).data()); + fprintf(stderr, formatColors("[info]%s┃ Content type: [help]%s[blank]\n").data(), endbar, inferMIMEType(fileContents(path.data.raw).value()).value_or("text/plain").data()); } else { size_t files = 0; size_t directories = 0; - fprintf(stderr, formatColors("[info]%s┃ Content size: [help]%s[blank]\n").data(), generatedEndbar().data(), formatBytes(totalDirectorySize(path.data)).data()); + fprintf(stderr, formatColors("[info]%s┃ Content size: [help]%s[blank]\n").data(), endbar, formatBytes(totalDirectorySize(path.data)).data()); for (const auto& entry : fs::directory_iterator(path.data)) entry.is_directory() ? directories++ : files++; - fprintf(stderr, formatColors("[info]%s┃ Files: [help]%zu[blank]\n").data(), generatedEndbar().data(), files); - fprintf(stderr, formatColors("[info]%s┃ Directories: [help]%zu[blank]\n").data(), generatedEndbar().data(), directories); + fprintf(stderr, formatColors("[info]%s┃ Files: [help]%zu[blank]\n").data(), endbar, files); + fprintf(stderr, formatColors("[info]%s┃ Directories: [help]%zu[blank]\n").data(), endbar, directories); } if (!available_mimes.empty()) { - fprintf(stderr, formatColors("[info]%s┃ Available types from GUI: [help]").data(), generatedEndbar().data()); + fprintf(stderr, formatColors("[info]%s┃ Available types from GUI: [help]").data(), endbar); for (const auto& mime : available_mimes) { fprintf(stderr, "%s", mime.data()); if (mime != available_mimes.back()) fprintf(stderr, ", "); } fprintf(stderr, "%s", formatColors("[blank]\n").data()); } - fprintf(stderr, formatColors("[info]%s┃ Content cut? [help]%s[blank]\n").data(), generatedEndbar().data(), fs::exists(path.metadata.originals) ? "Yes" : "No"); + fprintf(stderr, formatColors("[info]%s┃ Content cut? [help]%s[blank]\n").data(), endbar, fs::exists(path.metadata.originals) ? "Yes" : "No"); - fprintf(stderr, formatColors("[info]%s┃ Locked by another process? [help]%s[blank]\n").data(), generatedEndbar().data(), path.isLocked() ? "Yes" : "No"); + fprintf(stderr, formatColors("[info]%s┃ Locked by another process? [help]%s[blank]\n").data(), endbar, path.isLocked() ? "Yes" : "No"); if (path.isLocked()) { - fprintf(stderr, formatColors("[info]%s┃ Locked by process with pid [help]%s[blank]\n").data(), generatedEndbar().data(), fileContents(path.metadata.lock).value().data()); + fprintf(stderr, formatColors("[info]%s┃ Locked by process with pid [help]%s[blank]\n").data(), endbar, fileContents(path.metadata.lock).value().data()); } if (fs::exists(path.metadata.notes)) - fprintf(stderr, formatColors("[info]%s┃ Note: [help]%s[blank]\n").data(), generatedEndbar().data(), fileContents(path.metadata.notes).value().data()); + fprintf(stderr, formatColors("[info]%s┃ Note: [help]%s[blank]\n").data(), endbar, fileContents(path.metadata.notes).value().data()); else - fprintf(stderr, formatColors("[info]%s┃ There is no note for this clipboard.[blank]\n").data(), generatedEndbar().data()); + fprintf(stderr, formatColors("[info]%s┃ There is no note for this clipboard.[blank]\n").data(), endbar); if (path.holdsIgnoreRegexes()) { - fprintf(stderr, formatColors("[info]%s┃ Ignore regexes: [help]").data(), generatedEndbar().data()); + fprintf(stderr, formatColors("[info]%s┃ Ignore regexes: [help]").data(), endbar); auto regexes = fileLines(path.metadata.ignore); for (const auto& regex : regexes) { fprintf(stderr, "%s", regex.data()); @@ -127,7 +130,26 @@ void info() { } fprintf(stderr, "%s", formatColors("[blank]\n").data()); } else - fprintf(stderr, formatColors("[info]%s┃ There are no ignore regexes for this clipboard.[blank]\n").data(), generatedEndbar().data()); + fprintf(stderr, formatColors("[info]%s┃ There are no ignore regexes for this clipboard.[blank]\n").data(), endbar); + + if (fs::exists(path.metadata.ignore_secret)) { + // list only how many ignore secrets there are + auto secrets = fileLines(path.metadata.ignore_secret); + fprintf(stderr, formatColors("[info]%s┃ There are %zu ignore secrets for this clipboard.[blank]\n").data(), endbar, secrets.size()); + } else { + fprintf(stderr, formatColors("[info]%s┃ There are no ignore secrets for this clipboard.[blank]\n").data(), endbar); + } + + 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()); + } else { + fprintf(stderr, formatColors("[info]%s┃ Script: [help]%s[blank]\n").data(), endbar, makeControlCharactersVisible(removeExcessWhitespace(script)).data()); + } + } else { + fprintf(stderr, formatColors("[info]%s┃ There is no script for this clipboard.[blank]\n").data(), endbar); + } fprintf(stderr, "%s", formatColors("[info]┗").data()); int cols = thisTerminalSize().columns; diff --git a/src/cb/src/locales/en_us.cpp b/src/cb/src/locales/en_us.cpp index 9504c5c72..d40c5468b 100644 --- a/src/cb/src/locales/en_us.cpp +++ b/src/cb/src/locales/en_us.cpp @@ -72,7 +72,7 @@ Message help_message = "[info]┃ This is the Clipboard Project %s (commit %s), "[info]┃ You can also get more help in our Discord server at [bold]https://discord.gg/J6asnc3pEG[blank]\n" "[info][bold]┃ All Actions Available[blank]\n" "%s" - "[info]┃ Copyright (C) 2023 Jackson Huff. Licensed under the GPLv3.[blank]\n" + "[info]┃ Copyright (C) 2022-2024 Jackson Huff. Licensed under the GPLv3.[blank]\n" "[info]┃ This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to " "redistribute it under certain conditions.[blank]\n"; Message check_clipboard_status_message = "[info][bold]All your clipboards with content[nobold]"; diff --git a/src/cb/src/locales/es_co.cpp b/src/cb/src/locales/es_co.cpp index 60c741819..c15506c99 100644 --- a/src/cb/src/locales/es_co.cpp +++ b/src/cb/src/locales/es_co.cpp @@ -127,7 +127,7 @@ void setLanguageES_CO() { "-h[nobold], [bold]cb --help[nobold] o[bold] cb help[nobold].\n" "[info][bold]┃ All Actions Available[blank]\n" "%s" - "[info]┃ Copyright (C) 2023 Jackson Huff. Licensed under the GPLv3.[blank]\n" + "[info]┃ Copyright (C) 2022-2024 Jackson Huff. Licensed under the GPLv3.[blank]\n" "[info]┃ This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome " "to redistribute it under certain conditions.[blank]\n"; no_valid_action_message = "[error][inverse] ✘ [noinverse] No especificaste ninguna acción válida o se te olvidó. [help]⬤ Inténta usar o añadir [bold]cortar, " diff --git a/src/cb/src/locales/es_do.cpp b/src/cb/src/locales/es_do.cpp index 2efd5b281..f51e229e9 100644 --- a/src/cb/src/locales/es_do.cpp +++ b/src/cb/src/locales/es_do.cpp @@ -127,7 +127,7 @@ void setLanguageES_DO() { "-h[nobold], [bold]cb --help[nobold] o[bold] cb help[nobold].\n" "[info][bold]┃ All Actions Available[blank]\n" "%s" - "[info]┃ Copyright (C) 2023 Jackson Huff. Licensed under the GPLv3.[blank]\n" + "[info]┃ Copyright (C) 2022-2024 Jackson Huff. Licensed under the GPLv3.[blank]\n" "[info]┃ This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome " "to redistribute it under certain conditions.[blank]\n"; no_valid_action_message = "[error][inverse] ✘ [noinverse] No especificaste ninguna acción válida o se te olvidó. [help]⬤ Inténta usar o añadir [bold]cortar, " diff --git a/src/cb/src/locales/pt_br.cpp b/src/cb/src/locales/pt_br.cpp index 31d132c61..d9d7f2837 100644 --- a/src/cb/src/locales/pt_br.cpp +++ b/src/cb/src/locales/pt_br.cpp @@ -108,7 +108,7 @@ void setLanguagePT() { "-h[nobold], [bold]cb --help[nobold] ou[bold] cb help[nobold].\n" "[info][bold]┃ All Actions Available[blank]\n" "%s" - "[info]┃ Copyright (C) 2023 Jackson Huff. Licensed under the GPLv3.[blank]\n" + "[info]┃ Copyright (C) 2022-2024 Jackson Huff. Licensed under the GPLv3.[blank]\n" "[info]┃ Este programa vem com ABSOLUTAMENTE NENHUMA GARANTIA. Este é um software livre, e você é " "bem-vindo a redistribuí-lo sob certas condições.[blank]\n"; no_valid_action_message = "[error][inverse] ✘ [noinverse] Você não especificou uma ação válida (\"%s\"), ou esqueceu de incluí-la. [help]⬤ Tente utilizar " diff --git a/src/cb/src/locales/tr_tr.cpp b/src/cb/src/locales/tr_tr.cpp index e2ac2a8e7..d018c3aed 100644 --- a/src/cb/src/locales/tr_tr.cpp +++ b/src/cb/src/locales/tr_tr.cpp @@ -135,7 +135,7 @@ void setLanguageTR() { "[info][bold]┃ All Actions Available[blank]\n" "%s" "[info]┃ Discord sunucumuzdan daha fazla yardım alabilirsiniz: [bold]https://discord.gg/J6asnc3pEG[blank]\n" - "[info]┃ Copyright (C) 2023 Jackson Huff. Licensed under the GPLv3.[blank]\n" + "[info]┃ Copyright (C) 2022-2024 Jackson Huff. Licensed under the GPLv3.[blank]\n" "[info]┃ GPLv3 altında lisanslanmıştır.[blank]\n" "[info]┃ Bu program KESİNLİKLE HİÇBİR GARANTİ ile birlikte gelir. Bu ücretsiz bir yazılımdır ve belirli " "koşullar altında yeniden dağıtabilirsiniz.[blank]\n"; diff --git a/src/cb/src/utils/cowcopy.cpp b/src/cb/src/utils/cowcopy.cpp new file mode 100644 index 000000000..cb1d103b7 --- /dev/null +++ b/src/cb/src/utils/cowcopy.cpp @@ -0,0 +1,21 @@ +/* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. + Copyright (C) 2024 Jackson Huff and other contributors on GitHub.com + SPDX-License-Identifier: GPL-3.0-or-later + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .*/ +#include "../clipboard.hpp" +#if defined(__linux__) +#include +#include +#endif + diff --git a/src/cb/src/utils/formatting.cpp b/src/cb/src/utils/formatting.cpp index 168820eb9..60f80622b 100644 --- a/src/cb/src/utils/formatting.cpp +++ b/src/cb/src/utils/formatting.cpp @@ -91,6 +91,8 @@ std::string removeExcessWhitespace(const std::string_view& oldStr, size_t len) { std::string newStr; newStr.reserve(oldStr.size()); + if (len == 0) len = oldStr.size(); + // Remove all whitespace that isn't a single space (2+ spaces, and tabs) for (size_t i = 0; i < len && i < oldStr.size(); i++) { if (oldStr[i] == ' ') {