From 72acccb051409441c4b580a4d010d0af9fce4927 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Tue, 17 Sep 2019 21:45:38 +0300 Subject: [PATCH] Userland: Add copy and paste commands You can now copy into the system clipboard like this: $ copy hello friends or like this: $ copy < ReadMe.md or like this: $ copy --type png < /res/wallpapers/sunset-retro.png And paste just with $ paste or to view the copied type: $ paste --print-type --- Userland/copy.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++ Userland/paste.cpp | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 Userland/copy.cpp create mode 100644 Userland/paste.cpp diff --git a/Userland/copy.cpp b/Userland/copy.cpp new file mode 100644 index 0000000000..991f43c1b7 --- /dev/null +++ b/Userland/copy.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include + +struct Options { + String data; + String type { "text" }; +}; + +void print_usage(FILE* stream, const char* argv0) +{ + fprintf( + stream, + "Usage:\n" + "\t%s [--type type] text\n" + "\t%s [--type type] < file\n" + "\n" + "\t-t type, --type type\tPick a type.\n" + "\t-h, --help\t\tPrint this help message.\n", + argv0, + argv0); +} + +Options parse_options(int argc, char* argv[]) +{ + Options options; + + static struct option long_options[] = { + { "type", required_argument, 0, 't' }, + { "help", no_argument, 0, 'h' }, + { 0, 0, 0, 0 } + }; + while (true) { + int option_index; + int c = getopt_long(argc, argv, "t:h", long_options, &option_index); + if (c == -1) + break; + if (c == 0) + c = long_options[option_index].val; + + switch (c) { + case 't': + options.type = optarg; + break; + case 'h': + print_usage(stdout, argv[0]); + exit(0); + default: + print_usage(stderr, argv[0]); + exit(1); + } + } + + if (optind < argc) { + // Copy the rest of our command-line args. + StringBuilder builder; + bool first = true; + for (int i = optind; i < argc; i++) { + if (!first) + builder.append(' '); + first = false; + builder.append(argv[i]); + } + options.data = builder.to_string(); + } else { + // Copy our stdin. + CFile c_stdin; + bool success = c_stdin.open( + STDIN_FILENO, + CIODevice::OpenMode::ReadOnly, + CFile::ShouldCloseFileDescription::No); + ASSERT(success); + auto buffer = c_stdin.read_all(); + dbg() << "Read size " << buffer.size(); + options.data = String((char*)buffer.data(), buffer.size()); + } + + return options; +} + +int main(int argc, char* argv[]) +{ + Options options = parse_options(argc, argv); + + new GEventLoop; + + GClipboard& clipboard = GClipboard::the(); + clipboard.set_data(options.data, options.type); +} diff --git a/Userland/paste.cpp b/Userland/paste.cpp new file mode 100644 index 0000000000..2b5acce5d3 --- /dev/null +++ b/Userland/paste.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +struct Options { + bool print_type { false }; + bool no_newline { false }; +}; + +void print_usage(FILE* stream, const char* argv0) +{ + fprintf( + stream, + "Usage:\n" + "\t%s [--print-type] [--no-newline]\n" + "\n" + "\t--print-type\t\tDisplay the copied type.\n" + "\t-n, --no-newline\tDo not append a newline.\n" + "\t-h, --help\t\tPrint this help message.\n", + argv0); +} + +Options parse_options(int argc, char* argv[]) +{ + Options options; + + static struct option long_options[] = { + { "print-type", no_argument, 0, 'p' }, + { "no-newline", no_argument, 0, 'n' }, + { "help", no_argument, 0, 'h' }, + { 0, 0, 0, 0 } + }; + while (true) { + int option_index; + int c = getopt_long(argc, argv, "hn", long_options, &option_index); + if (c == -1) + break; + if (c == 0) + c = long_options[option_index].val; + + switch (c) { + case 'p': + options.print_type = true; + break; + case 'n': + options.no_newline = true; + break; + case 'h': + print_usage(stdout, argv[0]); + exit(0); + default: + print_usage(stderr, argv[0]); + exit(1); + } + } + + return options; +} + +int main(int argc, char* argv[]) +{ + Options options = parse_options(argc, argv); + + new GEventLoop; + + GClipboard& clipboard = GClipboard::the(); + auto data_and_type = clipboard.data_and_type(); + + if (!options.print_type) { + printf("%s", data_and_type.data.characters()); + // Append a newline to text contents, but + // only if we're not asked not to do this. + if (data_and_type.type == "text" && !options.no_newline) + putchar('\n'); + } else { + printf("%s\n", data_and_type.type.characters()); + } +}