mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-30 04:33:53 +00:00
Add environment variable processing to the configuration pointer. (#891)
Fixes #890 Add parsing of environmental variables when supplied for the config file option. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
84cad16974
commit
a1135bb30c
@ -223,6 +223,8 @@ CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
|
||||
/// Add quotes if the string contains spaces
|
||||
CLI11_INLINE std::string &add_quotes_if_needed(std::string &str);
|
||||
|
||||
/// get the value of an environmental variable or empty string if empty
|
||||
CLI11_INLINE std::string get_environment_value(const std::string &env_name);
|
||||
} // namespace detail
|
||||
|
||||
// [CLI11:string_tools_hpp:end]
|
||||
|
@ -1333,6 +1333,9 @@ template <class AssignTo,
|
||||
detail::enabler> = detail::dummy>
|
||||
bool lexical_conversion(const std::vector<std ::string> &strings, AssignTo &output) {
|
||||
output.erase(output.begin(), output.end());
|
||||
if(strings.empty()) {
|
||||
return true;
|
||||
}
|
||||
if(strings.size() == 1 && strings[0] == "{}") {
|
||||
return true;
|
||||
}
|
||||
|
@ -315,8 +315,11 @@ CLI11_INLINE Option *App::set_config(std::string option_name,
|
||||
}
|
||||
if(!default_filename.empty()) {
|
||||
config_ptr_->default_str(std::move(default_filename));
|
||||
config_ptr_->force_callback_ = true;
|
||||
}
|
||||
config_ptr_->configurable(false);
|
||||
// set the option to take the last value given by default
|
||||
config_ptr_->take_last();
|
||||
}
|
||||
|
||||
return config_ptr_;
|
||||
@ -1014,10 +1017,18 @@ CLI11_INLINE void App::_process_config_file() {
|
||||
if(config_ptr_ != nullptr) {
|
||||
bool config_required = config_ptr_->get_required();
|
||||
auto file_given = config_ptr_->count() > 0;
|
||||
if(!(file_given || config_ptr_->envname_.empty())) {
|
||||
std::string ename_string = detail::get_environment_value(config_ptr_->envname_);
|
||||
if(!ename_string.empty()) {
|
||||
config_ptr_->add_result(ename_string);
|
||||
}
|
||||
}
|
||||
config_ptr_->run_callback();
|
||||
|
||||
auto config_files = config_ptr_->as<std::vector<std::string>>();
|
||||
if(config_files.empty() || config_files.front().empty()) {
|
||||
if(config_required) {
|
||||
throw FileError::Missing("no specified config file");
|
||||
throw FileError("config file is required but none was given");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1028,9 +1039,6 @@ CLI11_INLINE void App::_process_config_file() {
|
||||
try {
|
||||
std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
|
||||
_parse_config(values);
|
||||
if(!file_given) {
|
||||
config_ptr_->add_result(config_file);
|
||||
}
|
||||
} catch(const FileError &) {
|
||||
if(config_required || file_given)
|
||||
throw;
|
||||
@ -1045,23 +1053,7 @@ CLI11_INLINE void App::_process_config_file() {
|
||||
CLI11_INLINE void App::_process_env() {
|
||||
for(const Option_p &opt : options_) {
|
||||
if(opt->count() == 0 && !opt->envname_.empty()) {
|
||||
char *buffer = nullptr;
|
||||
std::string ename_string;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Windows version
|
||||
std::size_t sz = 0;
|
||||
if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
|
||||
ename_string = std::string(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
#else
|
||||
// This also works on Windows, but gives a warning
|
||||
buffer = std::getenv(opt->envname_.c_str());
|
||||
if(buffer != nullptr)
|
||||
ename_string = std::string(buffer);
|
||||
#endif
|
||||
|
||||
std::string ename_string = detail::get_environment_value(opt->envname_);
|
||||
if(!ename_string.empty()) {
|
||||
opt->add_result(ename_string);
|
||||
}
|
||||
|
@ -255,6 +255,27 @@ CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string get_environment_value(const std::string &env_name) {
|
||||
char *buffer = nullptr;
|
||||
std::string ename_string;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Windows version
|
||||
std::size_t sz = 0;
|
||||
if(_dupenv_s(&buffer, &sz, env_name.c_str()) == 0 && buffer != nullptr) {
|
||||
ename_string = std::string(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
#else
|
||||
// This also works on Windows, but gives a warning
|
||||
buffer = std::getenv(env_name.c_str());
|
||||
if(buffer != nullptr) {
|
||||
ename_string = std::string(buffer);
|
||||
}
|
||||
#endif
|
||||
return ename_string;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
// [CLI11:string_tools_inl_hpp:end]
|
||||
} // namespace CLI
|
||||
|
@ -673,6 +673,36 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredNotDefault", "[config]") {
|
||||
CHECK(tmpini2.c_str() == app.get_config_ptr()->as<std::string>());
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(TApp, "IniEnvironmentalFileName", "[config]") {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
|
||||
app.set_config("--config", "")->envname("CONFIG")->required();
|
||||
|
||||
{
|
||||
std::ofstream out{tmpini};
|
||||
out << "[default]" << std::endl;
|
||||
out << "two=99" << std::endl;
|
||||
out << "three=3" << std::endl;
|
||||
}
|
||||
|
||||
int one{0}, two{0}, three{0};
|
||||
app.add_option("--one", one);
|
||||
app.add_option("--two", two);
|
||||
app.add_option("--three", three);
|
||||
|
||||
put_env("CONFIG", tmpini);
|
||||
|
||||
CHECK_NOTHROW(run());
|
||||
|
||||
CHECK(two == 99);
|
||||
CHECK(three == 3);
|
||||
|
||||
unset_env("CONFIG");
|
||||
|
||||
CHECK_THROWS_AS(run(), CLI::FileError);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(TApp, "MultiConfig", "[config]") {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
|
@ -1354,3 +1354,14 @@ TEST_CASE("FixNewLines: EdgesCheck", "[helpers]") {
|
||||
std::string result = CLI::detail::fix_newlines("; ", input);
|
||||
CHECK(output == result);
|
||||
}
|
||||
|
||||
TEST_CASE("String: environment", "[helpers]") {
|
||||
put_env("TEST1", "TESTS");
|
||||
|
||||
auto value = CLI::detail::get_environment_value("TEST1");
|
||||
CHECK(value == "TESTS");
|
||||
unset_env("TEST1");
|
||||
|
||||
value = CLI::detail::get_environment_value("TEST2");
|
||||
CHECK(value.empty());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user