parse CLI arguments v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Thu, 17 Jan 2019 13:14:37 +0100
branchv_0
changeset 10 3e1608320b6c
parent 9 b4f29fb16159
child 11 f12594938a03
parse CLI arguments
src/CLIParser.h
src/relpipe-in-filesystem.cpp
--- a/src/CLIParser.h	Wed Jan 16 19:31:37 2019 +0100
+++ b/src/CLIParser.h	Thu Jan 17 13:14:37 2019 +0100
@@ -20,6 +20,8 @@
 #include <vector>
 
 #include <relpipe/writer/typedefs.h>
+#include <relpipe/cli/CLI.h>
+#include <relpipe/cli/RelpipeCLIException.h>
 
 #include "Configuration.h"
 #include "FileAttributeFinder.h"
@@ -31,23 +33,72 @@
 using namespace relpipe::writer;
 
 class CLIParser {
+private:
+
+	string_t readNext(std::vector<string_t> arguments, int& i) {
+		if (i < arguments.size()) return arguments[i++];
+		else throw relpipe::cli::RelpipeCLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+	}
+
+	void addField(Configuration& c, string_t& group, string_t& name, std::vector<string_t>& aliases, std::map<string_t, string_t>& options) {
+		if (group.size()) {
+			c.fields.push_back(RequestedField(group, name, aliases, options));
+			group.clear();
+			name.clear();
+			aliases.clear();
+			options.clear();
+		}
+	}
+
 public:
 
+	static const string_t OPTION_FILE;
+	static const string_t OPTION_XATTR;
+	static const string_t OPTION_AS;
+	static const string_t OPTION_OPTION;
+
 	Configuration parse(const std::vector<string_t>& arguments) {
 		Configuration c;
-		// TODO: parse arguments
-		c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ORIGINAL));
-		// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ABSOLUTE));
-		// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_CANONICAL));
-		// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_NAME));
-		c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE));
-		// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE,{L"type_a", L"type_b"}));
-		c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET_TYPE));
-		// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET));
-		c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SIZE));
-		c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_OWNER));
-		c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_GROUP));
-		c.fields.push_back(RequestedField(RequestedField::GROUP_XATTR, L"user.xdg.origin.url"));
+		if (arguments.empty()) {
+			// default set of fields:
+			c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ORIGINAL));
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ABSOLUTE));
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_CANONICAL));
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_NAME));
+			c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE));
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE,{L"type_a", L"type_b"})); // one field → two attributes with same value
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET_TYPE));
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET));
+			c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SIZE));
+			c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_OWNER));
+			c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_GROUP));
+			// c.fields.push_back(RequestedField(RequestedField::GROUP_XATTR, L"user.xdg.origin.url"));
+		} else {
+			string_t currentGroup;
+			string_t currentName;
+			std::vector<string_t> currentAliases;
+			std::map<string_t, string_t> currentOptions;
+
+			for (int i = 0; i < arguments.size();) {
+				string_t option = readNext(arguments, i);
+
+				if (option == CLIParser::OPTION_FILE || option == CLIParser::OPTION_XATTR) {
+					addField(c, currentGroup, currentName, currentAliases, currentOptions); // previous field
+					currentGroup = option.substr(2); // cut off --
+					currentName = readNext(arguments, i);
+				} else if (option == OPTION_AS) {
+					currentAliases.push_back(readNext(arguments, i));
+				} else if (option == OPTION_OPTION) {
+					string_t key = readNext(arguments, i);
+					string_t value = readNext(arguments, i);
+					currentOptions[key] = value;
+				} else {
+					throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+				}
+			}
+			
+			addField(c, currentGroup, currentName, currentAliases, currentOptions); // last field
+		}
 		return c;
 	}
 
@@ -55,6 +106,11 @@
 	}
 };
 
+const string_t CLIParser::OPTION_FILE = L"--" + RequestedField::GROUP_FILE;
+const string_t CLIParser::OPTION_XATTR = L"--" + RequestedField::GROUP_XATTR;
+const string_t CLIParser::OPTION_AS = L"--as";
+const string_t CLIParser::OPTION_OPTION = L"--option";
+
 }
 }
 }
--- a/src/relpipe-in-filesystem.cpp	Wed Jan 16 19:31:37 2019 +0100
+++ b/src/relpipe-in-filesystem.cpp	Thu Jan 17 13:14:37 2019 +0100
@@ -28,6 +28,7 @@
 #include <relpipe/writer/TypeId.h>
 
 #include <relpipe/cli/CLI.h>
+#include <relpipe/cli/RelpipeCLIException.h>
 
 #include "FilesystemCommand.h"
 #include "CLIParser.h"
@@ -53,6 +54,10 @@
 		fwprintf(stderr, L"Caught Writer exception: %ls\n", e.getMessge().c_str());
 		fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount());
 		resultCode = CLI::EXIT_CODE_DATA_ERROR;
+	} catch (RelpipeCLIException e) {
+		fwprintf(stderr, L"Caught CLI exception: %ls\n", e.getMessge().c_str());
+		fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount());
+		resultCode = e.getExitCode();
 	}
 
 	return resultCode;