diff --git a/src/main.cc b/src/main.cc index d826029..4903259 100644 --- a/src/main.cc +++ b/src/main.cc @@ -13,14 +13,21 @@ static void show_usage(const bool include_help) static const auto help = "Options:\n" " -h, --help print this help\n" - " -o, --output write the modified tags to a file\n" + " -V, --version print version\n" + " -o, --output FILE write the modified tags to this file\n" " -i, --in-place [SUFFIX] use a temporary file then replace the original file\n" " -y, --overwrite overwrite the output file if it already exists\n" + " --stream ID select stream for the next operations\n" + " -l, --list display a pretty listing of all tags\n" + " --no-color disable colors in --list output\n" " -d, --delete FIELD delete all the fields of a specified type\n" " -a, --add FIELD=VALUE add a field\n" " -s, --set FIELD=VALUE delete then add a field\n" " -D, --delete-all delete all the fields!\n" - " -S, --set-all read the fields from stdin\n"; + " --full enable full file scan\n" + " --export dump the tags to standard output for --import\n" + " --import set the tags from scratch basing on stanard input\n" + " -e, --edit spawn the $EDITOR and apply --import on the result\n"; std::cout << "opustags v" << version << "\n"; std::cout << usage; diff --git a/src/options.cc b/src/options.cc index 99c5f53..48965f9 100644 --- a/src/options.cc +++ b/src/options.cc @@ -2,6 +2,10 @@ #include #include "tags_handlers/insertion_tags_handler.h" #include "tags_handlers/modification_tags_handler.h" +#include "tags_handlers/external_edit_tags_handler.h" +#include "tags_handlers/export_tags_handler.h" +#include "tags_handlers/import_tags_handler.h" +#include "tags_handlers/listing_tags_handler.h" #include "tags_handlers/removal_tags_handler.h" #include "options.h" @@ -15,16 +19,18 @@ ArgumentError::ArgumentError(const std::string &message) Options::Options() : show_help(false), overwrite(false), - set_all(false) + full(false) { } Options opustags::parse_args(const int argc, char **argv) { - static const auto short_def = "ho:i::yd:a:s:DS"; + static const auto short_def = "hVeo:i::yd:a:s:Dl"; static const option long_def[] = { {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"full", no_argument, 0, 0}, {"output", required_argument, 0, 'o'}, {"in-place", optional_argument, 0, 'i'}, {"overwrite", no_argument, 0, 'y'}, @@ -32,12 +38,19 @@ Options opustags::parse_args(const int argc, char **argv) {"add", required_argument, 0, 'a'}, {"stream", required_argument, 0, 0}, {"set", required_argument, 0, 's'}, + {"list", no_argument, 0, 'l'}, {"delete-all", no_argument, 0, 'D'}, - {"set-all", no_argument, 0, 'S'}, + {"edit", no_argument, 0, 'e'}, + {"import", no_argument, 0, 0}, + {"export", no_argument, 0, 0}, + + // TODO: parse no-colors {nullptr, 0, 0, 0} }; + // TODO: use --list as default switch + Options options; int current_streamno = StreamTagsHandler::ALL_STREAMS; @@ -55,6 +68,10 @@ Options opustags::parse_args(const int argc, char **argv) options.show_help = true; break; + case 'V': + options.show_version = true; + break; + case 'o': if (arg.empty()) throw ArgumentError("Output path cannot be empty"); @@ -62,6 +79,8 @@ Options opustags::parse_args(const int argc, char **argv) break; case 'i': + // TODO: shouldn't we generate random file name here to which + // we apply the arg, rather than use the arg as a whole? options.path_out = arg.empty() ? ".otmp" : arg; options.in_place = true; break; @@ -100,8 +119,15 @@ Options opustags::parse_args(const int argc, char **argv) break; } - case 'S': - options.set_all = true; + case 'l': + options.tags_handler.add_handler( + std::make_shared( + current_streamno, std::cout)); + break; + + case 'e': + options.tags_handler.add_handler( + std::make_shared()); break; case 'D': @@ -114,6 +140,14 @@ Options opustags::parse_args(const int argc, char **argv) std::string long_arg = long_def[option_index].name; if (long_arg == "stream") current_streamno = atoi(optarg); + else if (long_arg == "full") + options.full = true; + else if (long_arg == "export") + options.tags_handler.add_handler( + std::make_shared(std::cout)); + else if (long_arg == "import") + options.tags_handler.add_handler( + std::make_shared(std::cin)); break; } diff --git a/src/options.h b/src/options.h index 6064a52..ce7e8f7 100644 --- a/src/options.h +++ b/src/options.h @@ -12,8 +12,9 @@ namespace opustags Options(); bool show_help; + bool show_version; bool overwrite; - bool set_all; + bool full; bool in_place; std::string path_in; diff --git a/src/tags_handlers/export_tags_handler.cc b/src/tags_handlers/export_tags_handler.cc new file mode 100644 index 0000000..0b7169d --- /dev/null +++ b/src/tags_handlers/export_tags_handler.cc @@ -0,0 +1,27 @@ +#include "tags_handlers/export_tags_handler.h" + +using namespace opustags; + +ExportTagsHandler::ExportTagsHandler(std::ostream &output_stream) + : output_stream(output_stream) +{ +} + +bool ExportTagsHandler::relevant(const int streamno) +{ + return false; +} + +void ExportTagsHandler::list(const int streamno, const Tags &) +{ +} + +bool ExportTagsHandler::edit(const int streamno, Tags &) +{ + return false; +} + +bool ExportTagsHandler::done() +{ + return true; +} diff --git a/src/tags_handlers/export_tags_handler.h b/src/tags_handlers/export_tags_handler.h new file mode 100644 index 0000000..b139254 --- /dev/null +++ b/src/tags_handlers/export_tags_handler.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "tags_handler.h" + +namespace opustags { + + class ExportTagsHandler : public ITagsHandler + { + public: + ExportTagsHandler(std::ostream &output_stream); + + bool relevant(const int streamno) override; + void list(const int streamno, const Tags &) override; + bool edit(const int streamno, Tags &) override; + bool done() override; + + private: + std::ostream &output_stream; + }; + +} diff --git a/src/tags_handlers/external_edit_tags_handler.cc b/src/tags_handlers/external_edit_tags_handler.cc new file mode 100644 index 0000000..4ee153d --- /dev/null +++ b/src/tags_handlers/external_edit_tags_handler.cc @@ -0,0 +1,22 @@ +#include "tags_handlers/external_edit_tags_handler.h" + +using namespace opustags; + +bool ExternalEditTagsHandler::relevant(const int streamno) +{ + return false; +} + +void ExternalEditTagsHandler::list(const int streamno, const Tags &) +{ +} + +bool ExternalEditTagsHandler::edit(const int streamno, Tags &) +{ + return false; +} + +bool ExternalEditTagsHandler::done() +{ + return true; +} diff --git a/src/tags_handlers/external_edit_tags_handler.h b/src/tags_handlers/external_edit_tags_handler.h new file mode 100644 index 0000000..d8a0525 --- /dev/null +++ b/src/tags_handlers/external_edit_tags_handler.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include "tags_handler.h" + +namespace opustags { + + class ExternalEditTagsHandler : public ITagsHandler + { + public: + bool relevant(const int streamno) override; + void list(const int streamno, const Tags &) override; + bool edit(const int streamno, Tags &) override; + bool done() override; + }; + +} diff --git a/src/tags_handlers/import_tags_handler.cc b/src/tags_handlers/import_tags_handler.cc new file mode 100644 index 0000000..3e88c25 --- /dev/null +++ b/src/tags_handlers/import_tags_handler.cc @@ -0,0 +1,27 @@ +#include "tags_handlers/import_tags_handler.h" + +using namespace opustags; + +ImportTagsHandler::ImportTagsHandler(std::istream &input_stream) + : input_stream(input_stream) +{ +} + +bool ImportTagsHandler::relevant(const int streamno) +{ + return false; +} + +void ImportTagsHandler::list(const int streamno, const Tags &) +{ +} + +bool ImportTagsHandler::edit(const int streamno, Tags &) +{ + return false; +} + +bool ImportTagsHandler::done() +{ + return true; +} diff --git a/src/tags_handlers/import_tags_handler.h b/src/tags_handlers/import_tags_handler.h new file mode 100644 index 0000000..a0024a6 --- /dev/null +++ b/src/tags_handlers/import_tags_handler.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "tags_handler.h" + +namespace opustags { + + class ImportTagsHandler : public ITagsHandler + { + public: + ImportTagsHandler(std::istream &input_stream); + + bool relevant(const int streamno) override; + void list(const int streamno, const Tags &) override; + bool edit(const int streamno, Tags &) override; + bool done() override; + + private: + std::istream &input_stream; + }; + +} diff --git a/tests/options_test.cc b/tests/options_test.cc index 64b296b..137c1bf 100644 --- a/tests/options_test.cc +++ b/tests/options_test.cc @@ -1,8 +1,12 @@ #include "options.h" #include #include "catch.h" -#include "tags_handlers/modification_tags_handler.h" +#include "tags_handlers/export_tags_handler.h" +#include "tags_handlers/external_edit_tags_handler.h" +#include "tags_handlers/import_tags_handler.h" #include "tags_handlers/insertion_tags_handler.h" +#include "tags_handlers/listing_tags_handler.h" +#include "tags_handlers/modification_tags_handler.h" #include "tags_handlers/removal_tags_handler.h" using namespace opustags; @@ -48,20 +52,25 @@ TEST_CASE("option parsing", "[options]") { SECTION("--help") { REQUIRE(retrieve_options({"--help"}).show_help); - REQUIRE(retrieve_options({"--h"}).show_help); + REQUIRE(retrieve_options({"-h"}).show_help); REQUIRE(!retrieve_options({}).show_help); } + SECTION("--version") { + REQUIRE(retrieve_options({"--version"}).show_version); + REQUIRE(retrieve_options({"-V"}).show_version); + REQUIRE(!retrieve_options({}).show_version); + } + SECTION("--overwrite") { REQUIRE(retrieve_options({"--overwrite"}).overwrite); REQUIRE(retrieve_options({"-y"}).overwrite); REQUIRE(!retrieve_options({}).overwrite); } - SECTION("--set-all") { - REQUIRE(retrieve_options({"--set-all"}).set_all); - REQUIRE(retrieve_options({"-S"}).set_all); - REQUIRE(!retrieve_options({}).set_all); + SECTION("--full") { + REQUIRE(retrieve_options({"--full"}).full); + REQUIRE(!retrieve_options({}).full); } SECTION("--in-place") { @@ -96,6 +105,29 @@ TEST_CASE("option parsing", "[options]") REQUIRE_THROWS(retrieve_options({"-o", ""})); } + SECTION("--import") { + get_handler(retrieve_options({"--import"}), 0); + } + + SECTION("--export") { + get_handler(retrieve_options({"--export"}), 0); + } + + SECTION("--edit") { + get_handler(retrieve_options({"--edit"}), 0); + get_handler(retrieve_options({"-e"}), 0); + } + + SECTION("--list") { + get_handler(retrieve_options({"--list"}), 0); + get_handler(retrieve_options({"-l"}), 0); + // TODO: + // test enabling / disabling colors, which should be + // contained inside the state of ListingTagsHandler + // TODO: + // it should be the default operation for readonly mode - test this too + } + SECTION("--delete-all") { REQUIRE(get_handler( retrieve_options({"--delete-all"}), 0)->get_tag_key().empty());