29 namespace filesystem { |
31 namespace filesystem { |
30 |
32 |
31 using namespace relpipe::writer; |
33 using namespace relpipe::writer; |
32 |
34 |
33 class CLIParser { |
35 class CLIParser { |
|
36 private: |
|
37 |
|
38 string_t readNext(std::vector<string_t> arguments, int& i) { |
|
39 if (i < arguments.size()) return arguments[i++]; |
|
40 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); |
|
41 } |
|
42 |
|
43 void addField(Configuration& c, string_t& group, string_t& name, std::vector<string_t>& aliases, std::map<string_t, string_t>& options) { |
|
44 if (group.size()) { |
|
45 c.fields.push_back(RequestedField(group, name, aliases, options)); |
|
46 group.clear(); |
|
47 name.clear(); |
|
48 aliases.clear(); |
|
49 options.clear(); |
|
50 } |
|
51 } |
|
52 |
34 public: |
53 public: |
|
54 |
|
55 static const string_t OPTION_FILE; |
|
56 static const string_t OPTION_XATTR; |
|
57 static const string_t OPTION_AS; |
|
58 static const string_t OPTION_OPTION; |
35 |
59 |
36 Configuration parse(const std::vector<string_t>& arguments) { |
60 Configuration parse(const std::vector<string_t>& arguments) { |
37 Configuration c; |
61 Configuration c; |
38 // TODO: parse arguments |
62 if (arguments.empty()) { |
39 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ORIGINAL)); |
63 // default set of fields: |
40 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ABSOLUTE)); |
64 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ORIGINAL)); |
41 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_CANONICAL)); |
65 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ABSOLUTE)); |
42 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_NAME)); |
66 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_CANONICAL)); |
43 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE)); |
67 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_NAME)); |
44 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE,{L"type_a", L"type_b"})); |
68 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE)); |
45 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET_TYPE)); |
69 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE,{L"type_a", L"type_b"})); // one field → two attributes with same value |
46 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET)); |
70 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET_TYPE)); |
47 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SIZE)); |
71 // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SYMLINK_TARGET)); |
48 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_OWNER)); |
72 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SIZE)); |
49 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_GROUP)); |
73 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_OWNER)); |
50 c.fields.push_back(RequestedField(RequestedField::GROUP_XATTR, L"user.xdg.origin.url")); |
74 c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_GROUP)); |
|
75 // c.fields.push_back(RequestedField(RequestedField::GROUP_XATTR, L"user.xdg.origin.url")); |
|
76 } else { |
|
77 string_t currentGroup; |
|
78 string_t currentName; |
|
79 std::vector<string_t> currentAliases; |
|
80 std::map<string_t, string_t> currentOptions; |
|
81 |
|
82 for (int i = 0; i < arguments.size();) { |
|
83 string_t option = readNext(arguments, i); |
|
84 |
|
85 if (option == CLIParser::OPTION_FILE || option == CLIParser::OPTION_XATTR) { |
|
86 addField(c, currentGroup, currentName, currentAliases, currentOptions); // previous field |
|
87 currentGroup = option.substr(2); // cut off -- |
|
88 currentName = readNext(arguments, i); |
|
89 } else if (option == OPTION_AS) { |
|
90 currentAliases.push_back(readNext(arguments, i)); |
|
91 } else if (option == OPTION_OPTION) { |
|
92 string_t key = readNext(arguments, i); |
|
93 string_t value = readNext(arguments, i); |
|
94 currentOptions[key] = value; |
|
95 } else { |
|
96 throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
|
97 } |
|
98 } |
|
99 |
|
100 addField(c, currentGroup, currentName, currentAliases, currentOptions); // last field |
|
101 } |
51 return c; |
102 return c; |
52 } |
103 } |
53 |
104 |
54 virtual ~CLIParser() { |
105 virtual ~CLIParser() { |
55 } |
106 } |
56 }; |
107 }; |
57 |
108 |
|
109 const string_t CLIParser::OPTION_FILE = L"--" + RequestedField::GROUP_FILE; |
|
110 const string_t CLIParser::OPTION_XATTR = L"--" + RequestedField::GROUP_XATTR; |
|
111 const string_t CLIParser::OPTION_AS = L"--as"; |
|
112 const string_t CLIParser::OPTION_OPTION = L"--option"; |
|
113 |
58 } |
114 } |
59 } |
115 } |
60 } |
116 } |