30 [](std::string
const& name) -> std::optional<std::string> {
31 if (
auto p = std::getenv(name.c_str()))
return std::string(
p);
43 template <ConfigurationValue T>
47 if (parsed_)
throw std::logic_error(
"configuration bindings must precede parsing");
48 if (!option)
throw std::invalid_argument(
"null CLI option");
49 if constexpr (!std::same_as<T, bool>)
50 if (option->get_type_size_max() == 0)
51 throw std::invalid_argument(
"only boolean flags can be configuration bindings");
52 if (std::ranges::any_of(options_, [&](
auto const& b) {
return b.option == option; }))
53 throw std::invalid_argument(
"CLI option already bound");
54 auto& binding = values_.
add<T>(id, target);
56 if (!option->get_envname().empty()) binding.
environment(option->get_envname());
57 option->envname(
"")->configurable(
false);
63 target =
value.get<T>();
66 if (
value.missing())
throw std::invalid_argument(
"missing value for CLI scalar option");
68 if constexpr (std::same_as<T, std::string>)
69 return value.text({},
true);
71 return value.type() ==
typeid(std::string) ?
value.get<std::string>()
75 option->add_result(
text);
76 option->run_callback();
79 options_.push_back({option, std::move(
id), [&target] {
return metadata_value(target); }});
86 if (parsed_ || file_option_)
throw std::logic_error(
"option file must be declared once before parsing");
87 file_option_ = app_.add_option(std::move(names), file_path_,
"Read selected options from a TOML/INI file");
88 file_option_->configurable(
false);
94 if (parsed_)
throw std::logic_error(
"configuration parser is single-use");
95 if (app_.get_config_ptr())
96 throw std::invalid_argument(
"use configuration::option_file instead of CLI11 set_config");
98 for (
auto const& b : options_)
100 for (
auto const* other : app_.get_options())
101 if (other->get_needs().contains(b.option) || other->get_excludes().contains(b.option))
102 throw
std::invalid_argument(
"resolve cross-option constraints after configuration sources");
103 if (!b.option->get_needs().empty() || !b.option->get_excludes().empty() || b.option->get_trigger_on_parse() ||
104 b.option->get_force_callback() || b.option->get_expected_max() > 1 || b.option->get_type_size_max() > 1)
105 throw std::invalid_argument(
"bound configuration options must be independent scalar options");
107 std::vector<bool> required;
108 for (
auto const& b : options_)
110 required.push_back(b.option->get_required());
111 if (b.option->get_required()) values_.binding(b.id).required().without_default();
112 if (!b.option->get_envname().empty())
114 values_.binding(b.id).environment(b.option->get_envname());
115 b.option->envname(
"");
117 b.option->required(
false);
120 for (std::size_t i = 0; i < options_.size(); ++i)
121 options_[i].option->required(required[i]);
126 result =
cli::parse(app_, argc, argv, policy);
134 if (result.requested !=
action::run)
return result;
135 for (
auto const& b : options_)
136 if (b.option->
count())
138 values_.set(b.id, b.read());
139 values_.cli_.insert(b.id);
149 if (!ready_)
throw std::logic_error(
"configuration is not ready for resolution");
150 if (!file_option_ || !file_option_->count())
return;
152 for (
auto const& item : app_.get_config_formatter()->from_file(file_path_))
154 if (item.name ==
"++" || item.name ==
"--")
continue;
155 if (item.inputs.size() != 1)
throw std::invalid_argument(
"configuration file requires scalar values");
156 if (!fields.emplace(item.fullname(), item.inputs.front()).second)
157 throw std::invalid_argument(
"duplicate option-file key: " + item.fullname());
159 values_.option_file(file_path_, std::move(fields));
169 auto& table = report.table(
"Configuration sources (highest priority first)");
170 table.
column(
"Option").
column(
"Sources after explicit CLI/API input").preserve_tokens();
171 for (
auto const& option : options_)
173 auto const& b = values_.binding(option.id);
175 auto append = [&](std::string
text) {
176 if (!sources.empty()) sources +=
"; ";
179 if (b.file_) append(
"file key " + *b.file_);
180 if (b.attribute_) append(
"attribute " + b.attribute_->first +
":" + b.attribute_->second);
181 if (b.environment_) append(
"environment " + *b.environment_);
183 append(
"default " + b.default_->text());
184 else if (b.required_)
185 append(
"required after loading sources");
186 table.
row(option.option->get_name(), sources);
193 if (!ready_)
throw std::logic_error(
"configuration is not ready for resolution");
194 return values_.snapshot();
206 std::vector<bound_option> options_;
207 CLI::Option* file_option_ =
nullptr;
208 std::string file_path_;
209 bool parsed_ =
false;
Collect CLI input first, then resolve declared fallback sources after loading input attributes.
Definition cli/configuration.hpp:25
configuration(configuration const &)=delete
configuration & operator=(configuration const &)=delete
configuration_binding & bind(CLI::Option *option, T &target, std::string id)
Bind a declared CLI11 option to a stable metadata id, capturing its initialized value as default.
Definition cli/configuration.hpp:45
configuration(CLI::App &app, uni20::configuration::environment_reader environment=[](std::string const &name) -> std::optional< std::string > { if(auto p=std::getenv(name.c_str())) return std::string(p);return std::nullopt;})
Definition cli/configuration.hpp:27
parse_result parse(int argc, char const *const *argv, parse_policy policy={})
Definition cli/configuration.hpp:92
void load_option_file()
Read the explicitly requested file using CLI11's configured TOML/INI reader.
Definition cli/configuration.hpp:147
metadata_document resolve() const
Resolve all bindings, assigning native CLI variables and returning owned metadata.
Definition cli/configuration.hpp:191
uni20::configuration & values()
Definition cli/configuration.hpp:162
presentation::report_builder result_report(presentation::program_info const &program, parse_result const &result) const
Include declared fallback sources in help, without evaluating or opening them.
Definition cli/configuration.hpp:164
CLI::Option * option_file(std::string names="--config")
Register an explicit option-file path; help never opens the file.
Definition cli/configuration.hpp:84
A single declared scalar, with application-selected fallback sources.
Definition common/configuration.hpp:43
configuration_binding & required(bool value=true)
Definition common/configuration.hpp:60
configuration_binding & environment(std::string name)
Definition common/configuration.hpp:50
configuration_binding & without_default()
Require an actual source instead of treating the initialized variable as a fallback.
Definition common/configuration.hpp:66
Parser-independent configuration with CLI/API > file > attribute > environment > default precedence.
Definition common/configuration.hpp:103
configuration_binding & add(std::string id, T initial)
Definition common/configuration.hpp:113
std::function< std::optional< std::string >(std::string const &)> environment_reader
Definition common/configuration.hpp:105
void row(std::vector< formatted_cell > cells, std::source_location where=std::source_location::current())
Emit preformatted cells without discarding their numeric alignment semantics.
Definition display.cpp:448
streaming_table & column(std::string heading, column_width width_spec=width::share(), presentation::table_alignment alignment=presentation::table_alignment::right, column_format format={})
Builder for simple terminal reports with headings, status lines, fields, and tables.
Definition presentation.hpp:602
CLI11 option adapters, explicit parse outcomes and semantic application help.
Explicit source bindings and checked configuration resolution.
locale_t value
Definition data_table.cpp:49
presentation::styled_text text
Definition display.cpp:141
presentation::report_builder result_report(CLI::App const &app, presentation::program_info const &program, parse_result const &result)
Build the selected informational/error document; a run outcome has no document and is rejected.
Definition cli.cpp:190
parse_result parse(CLI::App &app, int argc, char const *const *argv, parse_policy policy)
Parse argc/argv, preserving CLI11's argument boundaries and help precedence.
Definition cli.cpp:116
Definition data_table.cpp:8
std::map< std::string, metadata_value > attribute_map
Definition common/configuration.hpp:26
Executable policy for empty invocations and usage failures.
Definition cli.hpp:39
Owned parse outcome; parsing itself does not print, open files or terminate the process.
Definition cli.hpp:48
action requested
Definition cli.hpp:49
Definition data_table.hpp:33
Application identity and explanatory content, independent of any option parser.
Definition program.hpp:32
Identifies the winning source, without retaining discarded candidates.
Definition metadata.hpp:275