29#include <unordered_set>
32#include <boost/algorithm/string/classification.hpp>
33#include <boost/algorithm/string/split.hpp>
34#include <boost/algorithm/string/trim.hpp>
35#include <boost/process/environment.hpp>
36#include <boost/regex.hpp>
43#include <SimoxUtility/algorithm/string/string_tools.h>
50 expandTildeSegments(std::string& text)
57 const char* home = std::getenv(
"HOME");
58 bool warnedHome =
false;
60 std::vector<std::string> segments;
61 boost::split(segments, text, boost::is_any_of(
":"));
62 for (
auto& seg : segments)
64 if (!seg.empty() && seg[0] ==
'~')
67 if (seg.size() == 1 || seg[1] ==
'/')
73 std::cerr <<
"[EnvExpander] Warning: HOME is not defined, cannot "
92 for (
size_t i = 0; i < segments.size(); ++i)
98 joined += segments[i];
117 if (not simox::alg::contains(input,
"="))
128 for (
const auto&
assign : assignments)
139 std::string expanded =
expand(input);
141 for (
const auto&
assign : assignments)
153 if (not simox::alg::contains(input,
"="))
160 std::vector<std::string> out;
161 out.reserve(assignments.size());
163 for (
const auto&
assign : assignments)
181 const char* existing = std::getenv(name.c_str());
182 std::string oldVal = (existing !=
nullptr) ? existing : std::string();
187 if (!oldExpanded.empty())
197 const char* existing = std::getenv(name.c_str());
198 std::string oldVal = (existing !=
nullptr) ? existing : std::string();
204 if (!oldExpanded.empty())
218 for (
size_t i = 0; i < out.size(); ++i)
230 std::vector<std::string>
233 std::vector<std::string> out;
234 boost::split(out, input, boost::is_any_of(
","));
238 std::tuple<std::string, EnvExpander::Operation, std::string>
241 auto pos = assignment.find(
'=');
242 if (pos == std::string::npos)
244 throw std::runtime_error(
"Invalid assignment: " + assignment);
247 std::string key = assignment.substr(0, pos);
248 std::string rhs = assignment.substr(pos + 1);
254 if (!rhs.empty() && rhs[0] ==
'+')
260 if (!key.empty() && key.back() ==
'+')
273 std::string result = value;
276 expandTildeSegments(result);
278 static const boost::regex reBraced(R
"(\$\{([A-Za-z_][A-Za-z0-9_]*)\})");
279 static const boost::regex reUnbraced(R
"(\$([A-Za-z_][A-Za-z0-9_]*))");
282 std::unordered_set<std::string> warned;
284 auto expand_match = [&](
const boost::smatch& m) -> std::string
286 std::string var = m[1].str();
287 const char* v = std::getenv(var.c_str());
291 if (!warned.count(var))
293 std::cerr <<
"[EnvExpander] Warning: environment variable '" << var
294 <<
"' is not defined\n";
299 return std::string(v);
302 result = boost::regex_replace(result, reBraced, expand_match);
303 result = boost::regex_replace(result, reUnbraced, expand_match);
311 const char* existing = std::getenv(name.c_str());
312 std::string oldVal = (existing !=
nullptr) ? existing :
"";
342 setenv(name.c_str(), newVal.c_str(), 1);
static std::vector< std::string > splitAssignments(const std::string &input)
static std::string expand(const std::string &input)
Return the expanded form of the comma-separated assignment list without modifying the process environ...
EnvExpander()
Construct an EnvExpander initialized with the current process environment.
static std::tuple< std::string, Operation, std::string > splitOperation(const std::string &assignment)
boost::process::environment env_
void applyOperation(const std::string &name, Operation op, const std::string &val)
static std::string expandVariables(const std::string &value)
void apply(const std::string &input, bool expandExisting=true)
Parse and apply the comma-separated assignment list to the internal environment env_ and to the proce...
This file is part of ArmarX.
std::optional< Eigen::Matrix< EigenT, rows, cols, Eigen::ColMajor > > & assign(std::optional< Eigen::Matrix< EigenT, rows, cols, Eigen::ColMajor > > &lh, const std::optional< Eigen::Matrix< EigenT, rows, cols, Eigen::RowMajor > > &rh)