13#include "arccore/common/internal/ProgramOptions.h"
20namespace Arcane::ProgramOptions
30 _parseNameString(
const std::string& name_str, std::string& long_name,
31 std::string& short_name,
bool& has_short)
33 auto pos = name_str.find(
',');
34 if (pos != std::string::npos) {
35 long_name = name_str.substr(0, pos);
36 short_name = name_str.substr(pos + 1);
51options_description(
const std::string& title)
58options_description::options_proxy options_description::
61 return options_proxy(*
this);
67void options_description::
68add_option(
const std::string& name,
69 std::shared_ptr<option_value> value_semantic,
70 const std::string& description)
72 option_descriptor opt;
73 _parseNameString(name, opt.long_name, opt.short_name, opt.has_short);
74 opt.description = description;
75 opt.value_semantic = std::move(value_semantic);
76 m_options.push_back(std::move(opt));
82const option_descriptor* options_description::
83find(
const std::string& name)
const
85 for (
const auto& opt : m_options) {
86 if (opt.long_name == name)
95const option_descriptor* options_description::
96find_by_short(
char short_name)
const
98 for (
const auto& opt : m_options) {
99 if (opt.has_short && !opt.short_name.empty() && opt.short_name[0] == short_name)
107options_description::options_proxy& options_description::options_proxy::
108operator()(
const char* name,
const char* description)
110 m_desc.add_option(name, std::make_shared<untyped_value>(), description);
116options_description::options_proxy& options_description::options_proxy::
117operator()(
const char* name,
118 const typed_value<bool>* value,
119 const char* description)
121 m_desc.add_option(name,
122 std::shared_ptr<option_value>(
const_cast<typed_value<bool>*
>(value)),
129options_description::options_proxy& options_description::options_proxy::
130operator()(
const char* name,
131 const typed_value<bool>* value)
133 m_desc.add_option(name,
134 std::shared_ptr<option_value>(
const_cast<typed_value<bool>*
>(value)),
142operator<<(std::ostream& os,
const options_description& desc)
144 if (!desc.m_title.empty())
145 os << desc.m_title <<
":\n";
147 for (
const auto& opt : desc.m_options) {
150 if (opt.has_short && !opt.short_name.empty()) {
151 if (opt.short_name.size() == 1 && std::isalnum(
static_cast<unsigned char>(opt.short_name[0])))
152 os <<
"-" << opt.short_name <<
" ";
154 os <<
"--" << opt.short_name <<
" ";
157 os <<
"[--" << opt.long_name;
159 if (opt.value_semantic && !opt.value_semantic->is_bool_switch())
164 if (opt.value_semantic && opt.value_semantic->has_default()) {
165 auto ds = opt.value_semantic->default_string();
167 os <<
" (=" << ds <<
")";
170 if (!opt.description.empty())
171 os <<
"\t" << opt.description;
182positional_options_description& positional_options_description::
183add(
const std::string& name,
int count)
185 m_options.emplace_back(name, count);
193add(
const std::string& name, variable_value value)
195 m_values[name] = std::move(value);
202count(
const std::string& name)
const
204 return m_values.find(name) != m_values.end();
210const variables_map::variable_value& variables_map::
211operator[](
const std::string& name)
const
213 static variable_value empty_value;
214 auto it = m_values.find(name);
215 if (it != m_values.end())
224set_semantic(
const std::string& name,
225 std::shared_ptr<option_value> semantic)
227 auto it = m_values.find(name);
228 if (it != m_values.end())
229 it->second.set_semantic(std::move(semantic));
242parsed_options command_line_parser::
245 parsed_options result(m_desc);
250 std::vector<std::string> positional_args;
251 bool end_of_options =
false;
253 for (
int i = 1; i < m_argc; ++i) {
254 std::string token(m_argv[i]);
256 if (end_of_options || token.empty() || token[0] !=
'-') {
257 positional_args.push_back(token);
263 end_of_options =
true;
267 if (token.size() >= 2 && token[1] ==
'-') {
271 bool has_eq_value =
false;
273 auto eq_pos = token.find(
'=', 2);
274 if (eq_pos != std::string::npos) {
275 name = token.substr(2, eq_pos - 2);
276 value = token.substr(eq_pos + 1);
280 name = token.substr(2);
286 const auto* opt = m_desc->find(name);
287 if (!opt || !opt->value_semantic)
290 if (opt->value_semantic->is_bool_switch()) {
291 result.add_option(name, { has_eq_value ? value :
"true" });
293 else if (opt->value_semantic->is_multitoken()) {
294 std::vector<std::string> values;
296 values.push_back(value);
297 while (i + 1 < m_argc) {
298 std::string next(m_argv[i + 1]);
299 if (!next.empty() && next[0] ==
'-' && next.size() > 1)
302 values.push_back(next);
304 result.add_option(name, std::move(values));
308 result.add_option(name, { value });
310 else if (i + 1 < m_argc) {
312 result.add_option(name, { std::string(m_argv[i]) });
318 if (token.size() < 2)
321 char short_char = token[1];
322 const auto* opt = m_desc->find_by_short(short_char);
323 if (!opt || !opt->value_semantic)
326 std::string name = opt->long_name;
327 std::string inline_value;
328 bool has_inline_value = (token.size() > 2);
330 if (has_inline_value)
331 inline_value = token.substr(2);
333 if (opt->value_semantic->is_bool_switch()) {
334 result.add_option(name, {
"true" });
336 else if (opt->value_semantic->is_multitoken()) {
337 std::vector<std::string> values;
338 if (has_inline_value)
339 values.push_back(inline_value);
340 while (i + 1 < m_argc) {
341 std::string next(m_argv[i + 1]);
342 if (!next.empty() && next[0] ==
'-' && next.size() > 1)
345 values.push_back(next);
347 result.add_option(name, std::move(values));
350 if (has_inline_value) {
351 result.add_option(name, { inline_value });
353 else if (i + 1 < m_argc) {
355 result.add_option(name, { std::string(m_argv[i]) });
362 if (m_positional && !positional_args.empty()) {
364 for (
const auto& pos_opt : m_positional->options()) {
365 if (pos_idx >= positional_args.size())
368 if (pos_opt.second == -1) {
370 std::vector<std::string> remaining(positional_args.begin() + pos_idx,
371 positional_args.end());
372 result.add_option(pos_opt.first, std::move(remaining));
376 int count = pos_opt.second;
377 std::vector<std::string> values;
378 for (
int c = 0; c < count && pos_idx < positional_args.size(); ++c, ++pos_idx)
379 values.push_back(positional_args[pos_idx]);
380 result.add_option(pos_opt.first, std::move(values));
392parse_command_line(
int argc,
char** argv,
const options_description& desc)
394 command_line_parser parser(argc, argv);
395 parser.options(desc);
408void store(
const parsed_options& parsed, variables_map& vm)
411 for (
const auto& po : parsed.options()) {
412 const auto* opt_desc = parsed.description().find(po.name);
413 if (!opt_desc || !opt_desc->value_semantic)
416 const auto& semantic = opt_desc->value_semantic;
418 if (po.values.empty())
421 if (semantic->is_multitoken()) {
422 std::any value = std::make_any<std::vector<std::string>>(po.values);
423 variables_map::variable_value vv(value,
false);
424 vv.set_semantic(semantic);
425 vm.add(po.name, std::move(vv));
428 std::any value = semantic->parse(po.values[0]);
429 variables_map::variable_value vv(value,
false);
430 vv.set_semantic(semantic);
431 vm.add(po.name, std::move(vv));
436 for (
const auto& opt : parsed.description().options()) {
437 if (!vm.count(opt.long_name) && opt.value_semantic && opt.value_semantic->has_default()) {
438 std::any default_val = opt.value_semantic->default_value_any();
439 variables_map::variable_value vv(default_val,
true);
440 vv.set_semantic(opt.value_semantic);
441 vm.add(opt.long_name, std::move(vv));
454void notify(variables_map& vm)
456 for (
auto& [name, val] : vm) {
459 if (
auto semantic = val.semantic())
460 semantic->assign_bound(val.value_ref());
std::ostream & operator<<(std::ostream &ostr, eItemKind item_kind)
Opérateur de sortie sur un flot.