$mermaidjs
CLI11 2.7.2
C++11 Command Line Interface Parser
Loading...
Searching...
No Matches
Option_inl.hpp
1// Copyright (c) 2017-2026, University of Cincinnati, developed by Henry Schreiner
2// under NSF AWARD 1414736 and by the respective contributors.
3// All rights reserved.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6
7#pragma once
8
9// IWYU pragma: private, include "CLI/CLI.hpp"
10
11// This include is only needed for IDEs to discover symbols
12#include "../Option.hpp"
13
14// [CLI11:public_includes:set]
15#include <algorithm>
16#include <cerrno>
17#include <cstdlib>
18#include <functional>
19#include <iterator>
20#include <memory>
21#include <set>
22#include <string>
23#include <tuple>
24#include <utility>
25#include <vector>
26// [CLI11:public_includes:end]
27
28namespace CLI {
29// [CLI11:option_inl_hpp:verbatim]
30
31template <typename CRTP> template <typename T> void OptionBase<CRTP>::copy_to(T *other) const {
32 other->group(group_);
33 other->required(required_);
34 other->ignore_case(ignore_case_);
35 other->ignore_underscore(ignore_underscore_);
36 other->configurable(configurable_);
37 other->disable_flag_override(disable_flag_override_);
38 other->delimiter(delimiter_);
39 other->always_capture_default(always_capture_default_);
40 other->multi_option_policy(multi_option_policy_);
41 other->callback_priority(callback_priority_);
42}
43
44CLI11_INLINE Option::Option(
45 std::string option_name, std::string option_description, callback_t callback, App *parent, bool allow_non_standard)
46 : description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
47 std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name), allow_non_standard);
48}
49
50CLI11_INLINE void Option::clear() {
51 results_.clear();
52 proc_results_.clear();
54}
55
56CLI11_INLINE Option *Option::expected(int value) {
57 if(value < 0) {
58 expected_min_ = -value;
61 }
62 allow_extra_args_ = true;
63 flag_like_ = false;
64 } else if(value == detail::expected_max_vector_size) {
65 expected_min_ = 1;
66 expected_max_ = detail::expected_max_vector_size;
67 allow_extra_args_ = true;
68 flag_like_ = false;
69 } else {
70 expected_min_ = value;
71 expected_max_ = value;
73 }
74 return this;
75}
76
77CLI11_INLINE Option *Option::expected(int value_min, int value_max) {
78 if(value_min < 0) {
79 value_min = -value_min;
80 }
81
82 if(value_max < 0) {
83 value_max = detail::expected_max_vector_size;
84 }
85 if(value_max < value_min) {
86 expected_min_ = value_max;
87 expected_max_ = value_min;
88 } else {
89 expected_max_ = value_max;
90 expected_min_ = value_min;
91 }
92
93 return this;
94}
95
96CLI11_INLINE Option *Option::check(Validator_p validator) {
97 validator->non_modifying();
98 validators_.push_back(std::move(validator));
99
100 return this;
101}
102
103CLI11_INLINE Option *Option::check(Validator validator, const std::string &validator_name) {
104 validator.non_modifying();
105 auto vp = std::make_shared<Validator>(std::move(validator));
106 if(!validator_name.empty()) {
107 vp->name(validator_name);
108 }
109 validators_.push_back(std::move(vp));
110
111 return this;
112}
113
114CLI11_INLINE Option *Option::check(std::function<std::string(const std::string &)> validator_func,
115 std::string validator_description,
116 std::string validator_name) {
117
118 auto vp = std::make_shared<Validator>(
119 std::move(validator_func), std::move(validator_description), std::move(validator_name));
120 vp->non_modifying();
121 validators_.push_back(std::move(vp));
122 return this;
123}
124
125CLI11_INLINE Option *Option::transform(Validator_p validator) {
126 validators_.insert(validators_.begin(), std::move(validator));
127
128 return this;
129}
130
131CLI11_INLINE Option *Option::transform(Validator validator, const std::string &transform_name) {
132 auto vp = std::make_shared<Validator>(std::move(validator));
133 if(!transform_name.empty()) {
134 vp->name(transform_name);
135 }
136 validators_.insert(validators_.begin(), std::move(vp));
137 return this;
138}
139
140CLI11_INLINE Option *
141Option::transform(Validator validator, const std::string &transform_description, const std::string &transform_name) {
142 auto vp = std::make_shared<Validator>(std::move(validator));
143 if(!transform_name.empty()) {
144 vp->name(transform_name);
145 }
146 vp->description(transform_description);
147 validators_.insert(validators_.begin(), std::move(vp));
148 return this;
149}
150
151CLI11_INLINE Option *Option::transform(const std::function<std::string(std::string)> &transform_func,
152 std::string transform_description,
153 std::string transform_name) {
154 auto vp = std::make_shared<Validator>(
155 [transform_func](std::string &val) {
156 val = transform_func(val);
157 return std::string{};
158 },
159 std::move(transform_description),
160 std::move(transform_name));
161 validators_.insert(validators_.begin(), std::move(vp));
162
163 return this;
164}
165
166CLI11_INLINE Option *Option::each(const std::function<void(std::string)> &func) {
167 auto vp = std::make_shared<Validator>(
168 [func](std::string &inout) {
169 func(inout);
170 return std::string{};
171 },
172 std::string{});
173 validators_.push_back(std::move(vp));
174 return this;
175}
176
177CLI11_INLINE Validator *Option::get_validator(const std::string &validator_name) {
178 for(auto &validator : validators_) {
179 if(validator_name == validator->get_name()) {
180 return validator.get();
181 }
182 }
183 if((validator_name.empty()) && (!validators_.empty())) {
184 return validators_.front().get();
185 }
186 throw OptionNotFound(std::string{"Validator "} + validator_name + " Not Found");
187}
188
189CLI11_INLINE Validator *Option::get_validator(int index) {
190 // This is a signed int so that it is not equivalent to a pointer.
191 if(index >= 0 && index < static_cast<int>(validators_.size())) {
192 return validators_[static_cast<decltype(validators_)::size_type>(index)].get();
193 }
194 throw OptionNotFound("Validator index is not valid");
195}
196
197CLI11_INLINE Option *Option::needs(Option *opt) {
198 if(opt != this) {
199 needs_.insert(opt);
200 }
201 return this;
202}
203
204CLI11_INLINE bool Option::remove_needs(Option *opt) {
205 auto iterator = std::find(std::begin(needs_), std::end(needs_), opt);
206
207 if(iterator == std::end(needs_)) {
208 return false;
209 }
210 needs_.erase(iterator);
211 return true;
212}
213
214CLI11_INLINE Option *Option::excludes(Option *opt) {
215 if(opt == this) {
216 throw(IncorrectConstruction("and option cannot exclude itself"));
217 }
218 excludes_.insert(opt);
219
220 // Help text should be symmetric - excluding a should exclude b
221 opt->excludes_.insert(this);
222
223 // Ignoring the insert return value, excluding twice is now allowed.
224 // (Mostly to allow both directions to be excluded by user, even though the library does it for you.)
225
226 return this;
227}
228
229CLI11_INLINE bool Option::remove_excludes(Option *opt) {
230 auto iterator = std::find(std::begin(excludes_), std::end(excludes_), opt);
231
232 if(iterator == std::end(excludes_)) {
233 return false;
234 }
235 excludes_.erase(iterator);
236 return true;
237}
238
239template <typename T> Option *Option::ignore_case(bool value) {
240 if(!ignore_case_ && value) {
241 ignore_case_ = value;
242 auto *parent = static_cast<T *>(parent_);
243 for(const Option_p &opt : parent->options_) {
244 if(opt.get() == this) {
245 continue;
246 }
247 const auto &omatch = opt->matching_name(*this);
248 if(!omatch.empty()) {
249 ignore_case_ = false;
250 throw OptionAlreadyAdded("adding ignore case caused a name conflict with " + omatch);
251 }
252 }
253 } else {
254 ignore_case_ = value;
255 }
256 return this;
257}
258
259template <typename T> Option *Option::ignore_underscore(bool value) {
260
261 if(!ignore_underscore_ && value) {
262 ignore_underscore_ = value;
263 auto *parent = static_cast<T *>(parent_);
264 for(const Option_p &opt : parent->options_) {
265 if(opt.get() == this) {
266 continue;
267 }
268 const auto &omatch = opt->matching_name(*this);
269 if(!omatch.empty()) {
270 ignore_underscore_ = false;
271 throw OptionAlreadyAdded("adding ignore underscore caused a name conflict with " + omatch);
272 }
273 }
274 } else {
275 ignore_underscore_ = value;
276 }
277 return this;
278}
279
280CLI11_INLINE Option *Option::multi_option_policy(MultiOptionPolicy value) {
281 if(value != multi_option_policy_) {
282 if(multi_option_policy_ == MultiOptionPolicy::Throw && expected_max_ == detail::expected_max_vector_size &&
283 expected_min_ > 1) { // this bizarre condition is to maintain backwards compatibility
284 // with the previous behavior of expected_ with vectors
286 }
287 multi_option_policy_ = value;
289 }
290 return this;
291}
292
293CLI11_NODISCARD CLI11_INLINE std::string
294Option::get_name(bool positional, bool all_options, bool disable_default_flag_values) const {
295 if(get_group().empty())
296 return {}; // Hidden
297
298 if(all_options) {
299
300 std::vector<std::string> name_list;
301
303 if((positional && (!pname_.empty())) || (snames_.empty() && lnames_.empty())) {
304 name_list.push_back(pname_);
305 }
306 if((get_items_expected() == 0) && (!fnames_.empty())) {
307 for(const std::string &sname : snames_) {
308 name_list.push_back("-" + sname);
309 if(!disable_default_flag_values && check_fname(sname)) {
310 name_list.back() += "{" + get_flag_value(sname, "") + "}";
311 }
312 }
313
314 for(const std::string &lname : lnames_) {
315 name_list.push_back("--" + lname);
316 if(!disable_default_flag_values && check_fname(lname)) {
317 name_list.back() += "{" + get_flag_value(lname, "") + "}";
318 }
319 }
320 } else {
321 for(const std::string &sname : snames_)
322 name_list.push_back("-" + sname);
323
324 for(const std::string &lname : lnames_)
325 name_list.push_back("--" + lname);
326 }
327
328 return detail::join(name_list);
329 }
330
331 // This returns the positional name no matter what
332 if(positional)
333 return pname_;
334
335 // Prefer long name
336 if(!lnames_.empty())
337 return std::string(2, '-') + lnames_[0];
338
339 // Or short name if no long name
340 if(!snames_.empty())
341 return std::string(1, '-') + snames_[0];
342
343 // If positional is the only name, it's okay to use that
344 return pname_;
345}
346
347CLI11_INLINE void Option::run_callback() {
348 bool used_default_str = false;
349 if(force_callback_ && results_.empty()) {
350 used_default_str = true;
352 }
354 _validate_results(results_);
356 }
357
359 _reduce_results(proc_results_, results_);
360 }
361
363 if(callback_) {
364 const results_t &send_results = proc_results_.empty() ? results_ : proc_results_;
365 if(send_results.empty()) {
366 return;
367 }
368 bool local_result = callback_(send_results);
369 if(used_default_str) {
370 // we only clear the results if the callback was actually used
371 // otherwise the callback is the storage of the default
372 results_.clear();
373 proc_results_.clear();
374 }
375 if(!local_result)
377 }
378}
379
380CLI11_NODISCARD CLI11_INLINE const std::string &Option::matching_name(const Option &other) const {
381 static const std::string estring;
382 bool bothConfigurable = configurable_ && other.configurable_;
383 for(const std::string &sname : snames_) {
384 if(other.check_sname(sname))
385 return sname;
386 if(bothConfigurable && other.check_lname(sname))
387 return sname;
388 }
389 for(const std::string &lname : lnames_) {
390 if(other.check_lname(lname))
391 return lname;
392 if(lname.size() == 1 && bothConfigurable) {
393 if(other.check_sname(lname)) {
394 return lname;
395 }
396 }
397 }
398 if(bothConfigurable && snames_.empty() && lnames_.empty() && !pname_.empty()) {
399 if(other.check_sname(pname_) || other.check_lname(pname_) || pname_ == other.pname_)
400 return pname_;
401 }
402 if(bothConfigurable && other.snames_.empty() && other.fnames_.empty() && !other.pname_.empty()) {
403 if(check_sname(other.pname_) || check_lname(other.pname_) || (pname_ == other.pname_))
404 return other.pname_;
405 }
406 if(ignore_case_ ||
407 ignore_underscore_) { // We need to do the inverse, in case we are ignore_case or ignore underscore
408 for(const std::string &sname : other.snames_)
409 if(check_sname(sname))
410 return sname;
411 for(const std::string &lname : other.lnames_)
412 if(check_lname(lname))
413 return lname;
414 }
415 return estring;
416}
417
418CLI11_NODISCARD CLI11_INLINE bool Option::check_name(const std::string &name) const {
419
420 if(name.length() > 2 && name[0] == '-' && name[1] == '-')
421 return check_lname(name.substr(2));
422 if(name.length() > 1 && name.front() == '-')
423 return check_sname(name.substr(1));
424 if(!pname_.empty()) {
425 std::string local_pname = pname_;
426 std::string local_name = name;
428 local_pname = detail::remove_underscore(local_pname);
429 local_name = detail::remove_underscore(local_name);
430 }
431 if(ignore_case_) {
432 local_pname = detail::to_lower(local_pname);
433 local_name = detail::to_lower(local_name);
434 }
435 if(local_name == local_pname) {
436 return true;
437 }
438 }
439
440 if(!envname_.empty()) {
441 // this needs to be the original since envname_ shouldn't match on case insensitivity
442 return (name == envname_);
443 }
444 return false;
445}
446
447CLI11_NODISCARD CLI11_INLINE std::string Option::get_flag_value(const std::string &name,
448 std::string input_value) const {
449 static const std::string trueString{"true"};
450 static const std::string falseString{"false"};
451 static const std::string emptyString{"{}"};
452 // check for disable flag override_
454 if(!((input_value.empty()) || (input_value == emptyString))) {
455 auto default_ind = detail::find_member(name, fnames_, ignore_case_, ignore_underscore_);
456 if(default_ind >= 0) {
457 // We can static cast this to std::size_t because it is more than 0 in this block
458 if(default_flag_values_[static_cast<std::size_t>(default_ind)].second != input_value) {
459 if(input_value == default_str_ && force_callback_) {
460 return input_value;
461 }
462 throw(ArgumentMismatch::FlagOverride(name));
463 }
464 } else {
465 if(input_value != trueString) {
466 throw(ArgumentMismatch::FlagOverride(name));
467 }
468 }
469 }
470 }
471 auto ind = detail::find_member(name, fnames_, ignore_case_, ignore_underscore_);
472 if((input_value.empty()) || (input_value == emptyString)) {
473 if(flag_like_) {
474 return (ind < 0) ? trueString : default_flag_values_[static_cast<std::size_t>(ind)].second;
475 }
476 return (ind < 0) ? default_str_ : default_flag_values_[static_cast<std::size_t>(ind)].second;
477 }
478 if(ind < 0) {
479 return input_value;
480 }
481 if(default_flag_values_[static_cast<std::size_t>(ind)].second == falseString) {
482 errno = 0;
483 auto val = detail::to_flag_value(input_value);
484 if(errno != 0) {
485 errno = 0;
486 return input_value;
487 }
488 return (val == 1) ? falseString : (val == (-1) ? trueString : std::to_string(-val));
489 }
490 return input_value;
491}
492
493CLI11_INLINE Option *Option::add_result(std::string s) {
494 _add_result(std::move(s), results_);
496 return this;
497}
498
499CLI11_INLINE Option *Option::add_result(std::string s, int &results_added) {
500 results_added = _add_result(std::move(s), results_);
502 return this;
503}
504
505CLI11_INLINE Option *Option::add_result(std::vector<std::string> s) {
507 for(auto &str : s) {
508 _add_result(std::move(str), results_);
509 }
510 return this;
511}
512
513CLI11_NODISCARD CLI11_INLINE results_t Option::reduced_results() const {
515 results_t res = (parsing || proc_results_.empty()) ? results_ : proc_results_;
517 if(parsing) {
518 _validate_results(res);
519 }
520 if(!res.empty()) {
521 results_t extra;
522 _reduce_results(extra, res);
523 if(!extra.empty()) {
524 res = std::move(extra);
525 }
526 }
527 }
528 return res;
529}
530
531CLI11_INLINE Option *Option::type_size(int option_type_size) {
532 if(option_type_size < 0) {
533 // this section is included for backwards compatibility
534 type_size_max_ = -option_type_size;
535 type_size_min_ = -option_type_size;
536 expected_max_ = detail::expected_max_vector_size;
537 } else {
538 type_size_max_ = option_type_size;
539 if(type_size_max_ < detail::expected_max_vector_size) {
540 type_size_min_ = option_type_size;
541 } else {
542 inject_separator_ = true;
543 }
544 if(type_size_max_ == 0)
545 required_ = false;
546 }
547 return this;
548}
549
550CLI11_INLINE Option *Option::type_size(int option_type_size_min, int option_type_size_max) {
551 if(option_type_size_min < 0 || option_type_size_max < 0) {
552 // this section is included for backwards compatibility
553 expected_max_ = detail::expected_max_vector_size;
554 option_type_size_min = (std::abs)(option_type_size_min);
555 option_type_size_max = (std::abs)(option_type_size_max);
556 }
557
558 if(option_type_size_min > option_type_size_max) {
559 type_size_max_ = option_type_size_min;
560 type_size_min_ = option_type_size_max;
561 } else {
562 type_size_min_ = option_type_size_min;
563 type_size_max_ = option_type_size_max;
564 }
565 if(type_size_max_ == 0) {
566 required_ = false;
567 }
568 if(type_size_max_ >= detail::expected_max_vector_size) {
569 inject_separator_ = true;
570 }
571 return this;
572}
573
574CLI11_NODISCARD CLI11_INLINE const std::string &Option::get_single_name() const {
575 if(!lnames_.empty()) {
576 return lnames_[0];
577 }
578 if(!snames_.empty()) {
579 return snames_[0];
580 }
581 if(!pname_.empty()) {
582 return pname_;
583 }
584 return envname_;
585}
586
587CLI11_INLINE Option *Option::type_name(std::string typeval) {
588 type_name_fn([typeval]() { return typeval; });
589 return this;
590}
591
595 }
596 return this;
597}
598
599CLI11_NODISCARD CLI11_INLINE std::string Option::get_type_name() const {
600 std::string full_type_name = type_name_();
601 if(!validators_.empty()) {
602 for(const auto &validator : validators_) {
603 std::string vtype = validator->get_description();
604 if(!vtype.empty()) {
605 full_type_name += ":" + vtype;
606 }
607 }
608 }
609 return full_type_name;
610}
611
612CLI11_INLINE void Option::_validate_results(results_t &res) const {
613 // Run the Validators (can change the string)
614 if(!validators_.empty()) {
615 if(type_size_max_ > 1) { // in this context index refers to the index in the type
616 int index = 0;
617 if(get_items_expected_max() < static_cast<int>(res.size()) &&
618 (multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast ||
619 multi_option_policy_ == CLI::MultiOptionPolicy::Reverse)) {
620 // create a negative index for the earliest ones
621 index = get_items_expected_max() - static_cast<int>(res.size());
622 }
623
624 for(std::string &result : res) {
625 if(detail::is_separator(result) && type_size_max_ != type_size_min_ && index >= 0) {
626 index = 0; // reset index for variable size chunks
627 continue;
628 }
629 auto err_msg = _validate(result, (index >= 0) ? (index % type_size_max_) : index);
630 if(!err_msg.empty())
631 throw ValidationError(get_name(), err_msg);
632 ++index;
633 }
634 } else {
635 int index = 0;
636 if(expected_max_ < static_cast<int>(res.size()) &&
637 (multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast ||
638 multi_option_policy_ == CLI::MultiOptionPolicy::Reverse)) {
639 // create a negative index for the earliest ones
640 index = expected_max_ - static_cast<int>(res.size());
641 }
642 for(std::string &result : res) {
643 auto err_msg = _validate(result, index);
644 ++index;
645 if(!err_msg.empty())
646 throw ValidationError(get_name(), err_msg);
647 }
648 }
649 }
650}
651
652CLI11_INLINE void Option::_reduce_results(results_t &out, const results_t &original) const {
653
654 // max num items expected or length of vector, always at least 1
655 // Only valid for a trimming policy
656
657 out.clear();
658 // Operation depends on the policy setting
659 switch(multi_option_policy_) {
660 case MultiOptionPolicy::TakeAll:
661 break;
662 case MultiOptionPolicy::TakeLast: {
663 // Allow multi-option sizes (including 0)
664 std::size_t trim_size = std::min<std::size_t>(
665 static_cast<std::size_t>(std::max<int>(get_items_expected_max(), 1)), original.size());
666 if(original.size() != trim_size) {
667 out.assign(original.end() - static_cast<results_t::difference_type>(trim_size), original.end());
668 }
669 } break;
670 case MultiOptionPolicy::Reverse: {
671 // Allow multi-option sizes (including 0)
672 std::size_t trim_size = std::min<std::size_t>(
673 static_cast<std::size_t>(std::max<int>(get_items_expected_max(), 1)), original.size());
674 if(original.size() != trim_size || trim_size > 1) {
675 out.assign(original.end() - static_cast<results_t::difference_type>(trim_size), original.end());
676 }
677 std::reverse(out.begin(), out.end());
678 } break;
679 case MultiOptionPolicy::TakeFirst: {
680 std::size_t trim_size = std::min<std::size_t>(
681 static_cast<std::size_t>(std::max<int>(get_items_expected_max(), 1)), original.size());
682 if(original.size() != trim_size) {
683 out.assign(original.begin(), original.begin() + static_cast<results_t::difference_type>(trim_size));
684 }
685 } break;
686 case MultiOptionPolicy::Join:
687 if(original.size() > 1) {
688 out.push_back(detail::join(original, std::string(1, (delimiter_ == '\0') ? '\n' : delimiter_)));
689 }
690 break;
691 case MultiOptionPolicy::Sum:
692 out.push_back(detail::sum_string_vector(original));
693 break;
694 case MultiOptionPolicy::Throw:
695 default: {
696 auto num_min = static_cast<std::size_t>(get_items_expected_min());
697 auto num_max = static_cast<std::size_t>(get_items_expected_max());
698 if(num_min == 0) {
699 num_min = 1;
700 }
701 if(num_max == 0) {
702 num_max = 1;
703 }
704 if(original.size() < num_min) {
705 throw ArgumentMismatch::AtLeast(get_name(), static_cast<int>(num_min), original.size());
706 }
707 if(original.size() > num_max) {
708 if(original.size() == 2 && num_max == 1 && original[1] == "%%" && original[0] == "{}") {
709 // this condition is a trap for the following empty indicator check on config files, it may not be used
710 // anymore
711 out = original; // LCOV_EXCL_LINE
712 } else {
713 throw ArgumentMismatch::AtMost(get_name(), static_cast<int>(num_max), original.size());
714 }
715 }
716 break;
717 }
718 }
719 // this check is to allow an empty vector in certain circumstances but not if expected is not zero.
720 // {} is the indicator for an empty container
721 if(out.empty()) {
722 if(original.size() == 1 && original[0] == "{}" && get_items_expected_min() > 0) {
723 out.emplace_back("{}");
724 out.emplace_back("%%");
725 }
726 } else if(out.size() == 1 && out[0] == "{}" && get_items_expected_min() > 0) {
727 out.emplace_back("%%");
728 }
729}
730
731CLI11_INLINE std::string Option::_validate(std::string &result, int index) const {
732 std::string err_msg;
733 if(result.empty() && expected_min_ == 0) {
734 // an empty with nothing expected is allowed
735 return err_msg;
736 }
737 for(const auto &vali : validators_) {
738 auto v = vali->get_application_index();
739 if(v == -1 || v == index) {
740 try {
741 err_msg = (*vali)(result);
742 } catch(const ValidationError &err) {
743 err_msg = err.what();
744 }
745 if(!err_msg.empty())
746 break;
747 }
748 }
749
750 return err_msg;
751}
752
753CLI11_INLINE int Option::_add_result(std::string &&result, std::vector<std::string> &res) const {
754 int result_count = 0;
755
756 // Handle the vector escape possibility all characters duplicated and starting with [[ ending with ]]
757 // this is always a single result
758 if(result.size() >= 4 && result[0] == '[' && result[1] == '[' && result.back() == ']' &&
759 (*(result.end() - 2) == ']')) {
760 // this is an escape clause for odd strings
761 std::string nstrs{'['};
762 bool duplicated{true};
763 for(std::size_t ii = 2; ii < result.size() - 2; ii += 2) {
764 if(result[ii] == result[ii + 1]) {
765 nstrs.push_back(result[ii]);
766 } else {
767 duplicated = false;
768 break;
769 }
770 }
771 if(duplicated) {
772 nstrs.push_back(']');
773 res.push_back(std::move(nstrs));
774 ++result_count;
775 return result_count;
776 }
777 }
778
779 if((allow_extra_args_ || get_expected_max() > 1 || get_type_size() > 1) && !result.empty() &&
780 result.front() == '[' &&
781 result.back() == ']') { // this is now a vector string likely from the default or user entry
782
783 result.pop_back();
784 result.erase(result.begin());
785 for(auto &var : CLI::detail::split_up(result, ',')) {
786 if(!var.empty()) {
787 result_count += _add_result(std::move(var), res);
788 }
789 }
790 return result_count;
791 }
792 if(delimiter_ == '\0') {
793 res.push_back(std::move(result));
794 ++result_count;
795 } else {
796 if((result.find_first_of(delimiter_) != std::string::npos)) {
797 for(const auto &var : CLI::detail::split(result, delimiter_)) {
798 if(!var.empty()) {
799 res.push_back(var);
800 ++result_count;
801 }
802 }
803 } else {
804 res.push_back(std::move(result));
805 ++result_count;
806 }
807 }
808 return result_count;
809}
810// [CLI11:option_inl_hpp:end]
811} // namespace CLI
Thrown when conversion call back fails, such as when an int fails to coerce to a string.
Definition Error.hpp:206
Thrown when an option is set to conflicting values (non-vector and multi args, for example).
Definition Error.hpp:97
Thrown when an option already exists.
Definition Error.hpp:145
bool always_capture_default_
Automatically capture default value.
Definition Option.hpp:96
MultiOptionPolicy multi_option_policy_
Policy for handling multiple arguments beyond the expected Max.
Definition Option.hpp:99
bool ignore_case_
Ignore the case when matching (option, not value).
Definition Option.hpp:81
bool configurable_
Allow this option to be given in a configuration file.
Definition Option.hpp:87
CallbackPriority callback_priority_
Priority of callback.
Definition Option.hpp:102
bool disable_flag_override_
Disable overriding flag values with '=value'.
Definition Option.hpp:90
bool required_
True if this is a required option.
Definition Option.hpp:78
char delimiter_
Specify a delimiter character for vector arguments.
Definition Option.hpp:93
std::string group_
The group membership.
Definition Option.hpp:75
bool ignore_underscore_
Ignore underscores when matching (option, not value).
Definition Option.hpp:84
CLI11_NODISCARD const std::string & get_group() const
Definition Option.hpp:136
void copy_to(T *other) const
Copy the contents to another similar class (one based on OptionBase).
Definition Option_inl.hpp:31
Definition Option.hpp:261
Option * type_size(int option_type_size)
Set a custom option size.
Definition Option_inl.hpp:531
Option * expected(int value)
Set the number of expected arguments.
Definition Option_inl.hpp:56
Option * check(Validator_p validator)
Adds a shared validator.
Definition Option_inl.hpp:96
std::string default_str_
A human readable default value, either manually set, captured, or captured by default.
Definition Option.hpp:296
CLI11_NODISCARD bool check_name(const std::string &name) const
Check a name. Requires "-" or "--" for short / long, supports positional name.
Definition Option_inl.hpp:418
std::function< std::string()> type_name_
Definition Option.hpp:304
@ reduced
a subset of results has been generated
Definition Option.hpp:355
@ callback_run
the callback has been executed
Definition Option.hpp:356
@ validated
the results have been validated
Definition Option.hpp:354
@ parsing
The option is currently collecting parsed results.
Definition Option.hpp:353
option_state current_option_state_
Whether the callback has run (needed for INI parsing).
Definition Option.hpp:359
int type_size_min_
The minimum number of arguments an option should be expecting.
Definition Option.hpp:317
CLI11_NODISCARD results_t reduced_results() const
Get a copy of the results.
Definition Option_inl.hpp:513
void clear()
Clear the parsed results (mostly for testing).
Definition Option_inl.hpp:50
Option * capture_default_str()
Capture the default value from the original value (if it can be captured).
Definition Option_inl.hpp:592
Option * needs(Option *opt)
Sets required options.
Definition Option_inl.hpp:197
CLI11_NODISCARD std::string get_type_name() const
Get the full typename for this option.
Definition Option_inl.hpp:599
CLI11_NODISCARD bool check_fname(std::string name) const
Requires "--" to be removed from string.
Definition Option.hpp:676
std::string pname_
A positional name.
Definition Option.hpp:283
int expected_min_
The minimum number of expected values.
Definition Option.hpp:320
Option * transform(Validator_p validator)
Adds a shared Validator.
Definition Option_inl.hpp:125
Option * ignore_case(bool value=true)
Definition Option_inl.hpp:239
std::set< Option * > needs_
A list of options that are required with this option.
Definition Option.hpp:328
void run_callback()
Process the callback.
Definition Option_inl.hpp:347
CLI11_NODISCARD std::string get_name(bool positional=false, bool all_options=false, bool disable_default_flag_values=false) const
Gets a comma separated list of names. Will include / prefer the positional name if positional is true...
Definition Option_inl.hpp:294
CLI11_NODISCARD bool check_sname(std::string name) const
Requires "-" to be removed from string.
Definition Option.hpp:666
bool flag_like_
Specify that the option should act like a flag vs regular option.
Definition Option.hpp:363
std::set< Option * > excludes_
A list of options that are excluded with this option.
Definition Option.hpp:331
bool force_callback_
flag indicating that the option should force the callback regardless if any results present
Definition Option.hpp:371
std::vector< std::string > fnames_
a list of flag names with specified default values;
Definition Option.hpp:280
CLI11_NODISCARD int get_items_expected_min() const
The total min number of expected string values to be used.
Definition Option.hpp:600
CLI11_NODISCARD const std::string & matching_name(const Option &other) const
If options share any of the same names, find it.
Definition Option_inl.hpp:380
CLI11_NODISCARD bool check_lname(std::string name) const
Requires "--" to be removed from string.
Definition Option.hpp:671
CLI11_NODISCARD int get_items_expected_max() const
Get the maximum number of items expected to be returned and used for the callback.
Definition Option.hpp:603
std::vector< std::string > snames_
A list of the short names (-a) without the leading dashes.
Definition Option.hpp:270
results_t proc_results_
results after reduction
Definition Option.hpp:350
bool remove_excludes(Option *opt)
Remove needs link from an option. Returns true if the option really was in the needs list.
Definition Option_inl.hpp:229
Option * multi_option_policy(MultiOptionPolicy value=MultiOptionPolicy::Throw)
Take the last argument if given multiple times (or another policy).
Definition Option_inl.hpp:280
std::vector< Validator_p > validators_
A list of Validators to run on each value parsed.
Definition Option.hpp:325
CLI11_NODISCARD const std::string & get_single_name() const
Get a single name for the option, first of lname, sname, pname, envname.
Definition Option_inl.hpp:574
Option * excludes(Option *opt)
Sets excluded options.
Definition Option_inl.hpp:214
App * parent_
link back up to the parent App for fallthrough
Definition Option.hpp:338
int expected_max_
The maximum number of expected values.
Definition Option.hpp:322
Option(std::string option_name, std::string option_description, callback_t callback, App *parent, bool allow_non_standard=false)
Making an option by hand is not defined, it must be made by the App class.
Definition Option_inl.hpp:44
CLI11_NODISCARD std::string get_flag_value(const std::string &name, std::string input_value) const
Definition Option_inl.hpp:447
CLI11_NODISCARD int get_items_expected() const
The total min number of expected string values to be used.
Definition Option.hpp:608
std::string description_
The description for help strings.
Definition Option.hpp:293
bool inject_separator_
flag indicating a separator needs to be injected after each argument call
Definition Option.hpp:367
Validator * get_validator(const std::string &validator_name="")
Get a named Validator.
Definition Option_inl.hpp:177
callback_t callback_
Options store a callback to do all the work.
Definition Option.hpp:341
CLI11_NODISCARD bool empty() const
True if the option was not passed.
Definition Option.hpp:391
CLI11_NODISCARD int get_expected_max() const
The max number of times the option expects to be included.
Definition Option.hpp:597
CLI11_NODISCARD int get_type_size() const
The number of arguments the option expects.
Definition Option.hpp:556
std::string envname_
If given, check the environment for this option.
Definition Option.hpp:286
std::function< std::string()> default_function_
Run this function to capture a default (ignore if empty).
Definition Option.hpp:307
Option * ignore_underscore(bool value=true)
Definition Option_inl.hpp:259
std::vector< std::pair< std::string, std::string > > default_flag_values_
Definition Option.hpp:277
Option * type_name_fn(std::function< std::string()> typefun)
Set the type function to run when displayed on this option.
Definition Option.hpp:758
int type_size_max_
Definition Option.hpp:315
bool allow_extra_args_
Specify that extra args beyond type_size_max should be allowed.
Definition Option.hpp:361
std::vector< std::string > lnames_
A list of the long names (--long) without the leading dashes.
Definition Option.hpp:273
Option * type_name(std::string typeval)
Set a custom option typestring.
Definition Option_inl.hpp:587
Option * add_result(std::string s)
Puts a result at the end.
Definition Option_inl.hpp:493
bool remove_needs(Option *opt)
Remove needs link from an option. Returns true if the option really was in the needs list.
Definition Option_inl.hpp:204
Option * each(const std::function< void(std::string)> &func)
Adds a user supplied function to run on each item passed in (communicate though lambda capture).
Definition Option_inl.hpp:166
results_t results_
complete Results of parsing
Definition Option.hpp:348
Thrown when counting a nonexistent option.
Definition Error.hpp:352
Some validators that are provided.
Definition Validators.hpp:55
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition Validators.hpp:123
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition Validators_inl.hpp:61
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition Validators.hpp:113