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