55 bool parseBoolean(const relpipe::reader::string_t& value) { |
57 bool parseBoolean(const relpipe::reader::string_t& value) { |
56 if (value == L"true") return true; |
58 if (value == L"true") return true; |
57 else if (value == L"false") return false; |
59 else if (value == L"false") return false; |
58 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse boolean value: " + value + L" (expecting true or false)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
60 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse boolean value: " + value + L" (expecting true or false)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
59 } |
61 } |
60 |
62 |
61 Configuration::ColorScheme parseColorScheme(const relpipe::reader::string_t& value) { |
63 Configuration::ColorScheme parseColorScheme(const relpipe::reader::string_t& value) { |
62 if (value == L"greenish") return Configuration::ColorScheme::Greenish; |
64 if (value == L"greenish") return Configuration::ColorScheme::Greenish; |
63 else if (value == L"amberish") return Configuration::ColorScheme::Amberish; |
65 else if (value == L"amberish") return Configuration::ColorScheme::Amberish; |
64 else if (value == L"black-and-white") return Configuration::ColorScheme::BlackAndWhite; |
66 else if (value == L"black-and-white") return Configuration::ColorScheme::BlackAndWhite; |
65 else if (value == L"midnight") return Configuration::ColorScheme::Midnight; |
67 else if (value == L"midnight") return Configuration::ColorScheme::Midnight; |
66 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse ColorScheme value: " + value + L" (expecting greenish, amberish, midnight or black-and-white)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
68 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse ColorScheme value: " + value + L" (expecting greenish, amberish, midnight or black-and-white)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
67 } |
69 } |
68 |
70 |
69 Configuration::TableStyle parseTableStyle(const relpipe::reader::string_t& value) { |
71 Configuration::TableStyle parseTableStyle(const relpipe::reader::string_t& value) { |
70 if (value == L"rounded") return Configuration::TableStyle::Rounded; |
72 if (value == L"rounded") return Configuration::TableStyle::Rounded; |
71 else if (value == L"sharp") return Configuration::TableStyle::Sharp; |
73 else if (value == L"sharp") return Configuration::TableStyle::Sharp; |
72 else if (value == L"sharp-double") return Configuration::TableStyle::SharpDouble; |
74 else if (value == L"sharp-double") return Configuration::TableStyle::SharpDouble; |
73 else if (value == L"horizontal-only") return Configuration::TableStyle::HorizontalOnly; |
75 else if (value == L"horizontal-only") return Configuration::TableStyle::HorizontalOnly; |
74 else if (value == L"ascii") return Configuration::TableStyle::Ascii; |
76 else if (value == L"ascii") return Configuration::TableStyle::Ascii; |
75 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse TableStyle value: " + value + L" (expecting rounded, sharp, ascii)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
77 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse TableStyle value: " + value + L" (expecting rounded, sharp, ascii)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
|
78 } |
|
79 |
|
80 /** |
|
81 * TODO: move to common parent class in relpipe-lib-cli |
|
82 * |
|
83 * @param cliArguments original CLI arguments |
|
84 * @param moduleName name of this program e.g. "relpipe-out-tabular" |
|
85 * @param supportedOptions options that could be specified also as environmental variables, not only CLI arguments, including the "--" prefix e.g. "--color-scheme" |
|
86 * @return defaults found in ENV + given CLI arguments |
|
87 */ |
|
88 const std::vector<relpipe::reader::string_t> addEnvDefaults(const std::vector<relpipe::reader::string_t>& cliArguments, const relpipe::reader::string_t moduleName, const std::vector<relpipe::reader::string_t>& supportedOptions) { |
|
89 std::vector<relpipe::reader::string_t> allArguments; |
|
90 |
|
91 auto toEnv = [](char ch) { |
|
92 return ch == '-' ? '_' : ::toupper(ch); |
|
93 }; |
|
94 |
|
95 std::string envPrefix = convertor.to_bytes(moduleName); |
|
96 transform(envPrefix.begin(), envPrefix.end(), envPrefix.begin(), toEnv); |
|
97 envPrefix.append("_"); |
|
98 |
|
99 for (auto o : supportedOptions) { |
|
100 if (o.substr(0, 2) == L"--") { |
|
101 std::string option = convertor.to_bytes(o); |
|
102 option.erase(0, 2); |
|
103 transform(option.begin(), option.end(), option.begin(), toEnv); |
|
104 |
|
105 // FIXME: check argument counts (should be specified alongside with supportedOptions) to avoid injection of unwanted options through ENV variables |
|
106 // TODO: allow repeated options? |
|
107 for (int i = -1; i < 10; i++) { |
|
108 std::string envName = i == -1 ? envPrefix + option : envPrefix + option + "_" + std::to_string(i); |
|
109 const char* value = std::getenv(envName.c_str()); |
|
110 if (value) { |
|
111 if (i == -1 || i == 0) allArguments.push_back(o); |
|
112 allArguments.push_back(convertor.from_bytes(value)); |
|
113 if (i == -1) break; |
|
114 } else { |
|
115 if (i > -1) break; |
|
116 } |
|
117 } |
|
118 } else { |
|
119 throw std::logic_error("supportedOptions must start with '--'"); |
|
120 } |
|
121 } |
|
122 |
|
123 for (auto a : cliArguments) allArguments.push_back(a); |
|
124 |
|
125 return allArguments; |
76 } |
126 } |
77 |
127 |
78 public: |
128 public: |
79 |
129 |
80 static const relpipe::reader::string_t OPTION_RELATION; |
130 static const relpipe::reader::string_t OPTION_RELATION; |
82 static const relpipe::reader::string_t OPTION_WRITE_RELATION_NAME; |
132 static const relpipe::reader::string_t OPTION_WRITE_RELATION_NAME; |
83 static const relpipe::reader::string_t OPTION_WRITE_RECORD_COUNT; |
133 static const relpipe::reader::string_t OPTION_WRITE_RECORD_COUNT; |
84 static const relpipe::reader::string_t OPTION_COLOR_SCHEME; |
134 static const relpipe::reader::string_t OPTION_COLOR_SCHEME; |
85 static const relpipe::reader::string_t OPTION_TABLE_STYLE; |
135 static const relpipe::reader::string_t OPTION_TABLE_STYLE; |
86 |
136 |
87 Configuration parse(const std::vector<relpipe::reader::string_t>& arguments) { |
137 Configuration parse(const std::vector<relpipe::reader::string_t>& cliArguments) { |
88 Configuration c; |
138 Configuration c; |
89 RelationConfiguration currentRelation; |
139 RelationConfiguration currentRelation; |
90 |
140 |
|
141 const std::vector<relpipe::reader::string_t> arguments = addEnvDefaults(cliArguments, L"relpipe-out-tabular",{OPTION_COLOR_SCHEME, OPTION_TABLE_STYLE}); |
|
142 |
91 // TODO: global configuration of writeTypes, writeRelationName, writeRecordCount |
143 // TODO: global configuration of writeTypes, writeRelationName, writeRecordCount |
92 |
144 |
93 for (int i = 0; i < arguments.size();) { |
145 for (int i = 0; i < arguments.size();) { |
94 relpipe::reader::string_t option = readNext(arguments, i); |
146 relpipe::reader::string_t option = readNext(arguments, i); |
95 |
147 |