mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-30 12:43:52 +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
|
/// Add quotes if the string contains spaces
|
||||||
CLI11_INLINE std::string &add_quotes_if_needed(std::string &str);
|
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
|
} // namespace detail
|
||||||
|
|
||||||
// [CLI11:string_tools_hpp:end]
|
// [CLI11:string_tools_hpp:end]
|
||||||
|
@ -1333,6 +1333,9 @@ template <class AssignTo,
|
|||||||
detail::enabler> = detail::dummy>
|
detail::enabler> = detail::dummy>
|
||||||
bool lexical_conversion(const std::vector<std ::string> &strings, AssignTo &output) {
|
bool lexical_conversion(const std::vector<std ::string> &strings, AssignTo &output) {
|
||||||
output.erase(output.begin(), output.end());
|
output.erase(output.begin(), output.end());
|
||||||
|
if(strings.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if(strings.size() == 1 && strings[0] == "{}") {
|
if(strings.size() == 1 && strings[0] == "{}") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -315,8 +315,11 @@ CLI11_INLINE Option *App::set_config(std::string option_name,
|
|||||||
}
|
}
|
||||||
if(!default_filename.empty()) {
|
if(!default_filename.empty()) {
|
||||||
config_ptr_->default_str(std::move(default_filename));
|
config_ptr_->default_str(std::move(default_filename));
|
||||||
|
config_ptr_->force_callback_ = true;
|
||||||
}
|
}
|
||||||
config_ptr_->configurable(false);
|
config_ptr_->configurable(false);
|
||||||
|
// set the option to take the last value given by default
|
||||||
|
config_ptr_->take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
return config_ptr_;
|
return config_ptr_;
|
||||||
@ -1014,10 +1017,18 @@ CLI11_INLINE void App::_process_config_file() {
|
|||||||
if(config_ptr_ != nullptr) {
|
if(config_ptr_ != nullptr) {
|
||||||
bool config_required = config_ptr_->get_required();
|
bool config_required = config_ptr_->get_required();
|
||||||
auto file_given = config_ptr_->count() > 0;
|
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>>();
|
auto config_files = config_ptr_->as<std::vector<std::string>>();
|
||||||
if(config_files.empty() || config_files.front().empty()) {
|
if(config_files.empty() || config_files.front().empty()) {
|
||||||
if(config_required) {
|
if(config_required) {
|
||||||
throw FileError::Missing("no specified config file");
|
throw FileError("config file is required but none was given");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1028,9 +1039,6 @@ CLI11_INLINE void App::_process_config_file() {
|
|||||||
try {
|
try {
|
||||||
std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
|
std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
|
||||||
_parse_config(values);
|
_parse_config(values);
|
||||||
if(!file_given) {
|
|
||||||
config_ptr_->add_result(config_file);
|
|
||||||
}
|
|
||||||
} catch(const FileError &) {
|
} catch(const FileError &) {
|
||||||
if(config_required || file_given)
|
if(config_required || file_given)
|
||||||
throw;
|
throw;
|
||||||
@ -1045,23 +1053,7 @@ CLI11_INLINE void App::_process_config_file() {
|
|||||||
CLI11_INLINE void App::_process_env() {
|
CLI11_INLINE void App::_process_env() {
|
||||||
for(const Option_p &opt : options_) {
|
for(const Option_p &opt : options_) {
|
||||||
if(opt->count() == 0 && !opt->envname_.empty()) {
|
if(opt->count() == 0 && !opt->envname_.empty()) {
|
||||||
char *buffer = nullptr;
|
std::string ename_string = detail::get_environment_value(opt->envname_);
|
||||||
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
|
|
||||||
|
|
||||||
if(!ename_string.empty()) {
|
if(!ename_string.empty()) {
|
||||||
opt->add_result(ename_string);
|
opt->add_result(ename_string);
|
||||||
}
|
}
|
||||||
|
@ -255,6 +255,27 @@ CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) {
|
|||||||
return 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
|
} // namespace detail
|
||||||
// [CLI11:string_tools_inl_hpp:end]
|
// [CLI11:string_tools_inl_hpp:end]
|
||||||
} // namespace CLI
|
} // namespace CLI
|
||||||
|
@ -673,6 +673,36 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredNotDefault", "[config]") {
|
|||||||
CHECK(tmpini2.c_str() == app.get_config_ptr()->as<std::string>());
|
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]") {
|
TEST_CASE_METHOD(TApp, "MultiConfig", "[config]") {
|
||||||
|
|
||||||
TempFile tmpini{"TestIniTmp.ini"};
|
TempFile tmpini{"TestIniTmp.ini"};
|
||||||
|
@ -1354,3 +1354,14 @@ TEST_CASE("FixNewLines: EdgesCheck", "[helpers]") {
|
|||||||
std::string result = CLI::detail::fix_newlines("; ", input);
|
std::string result = CLI::detail::fix_newlines("; ", input);
|
||||||
CHECK(output == result);
|
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