kranewl

A wlroots-based dynamic Wayland compositor, written in C++, configurable with Lua
git clone git://git.deurzen.net/kranewl
Log | Files | Refs | LICENSE

commit 1c45abe5e1bffc45f24f947552fc8725440d3447
parent ad0c3a48ce95c8bedfb12a7911a25b77e6247f36
Author: deurzen <max@deurzen.net>
Date:   Wed,  1 Jun 2022 14:55:34 +0200

implements nested env var evaluation

Diffstat:
Ainclude/kranewl/env.hh | 5+++++
Asrc/kranewl/env.cc | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/include/kranewl/env.hh b/include/kranewl/env.hh @@ -0,0 +1,5 @@ +#pragma once + +#include <string> + +void parse_and_set_env_vars(std::string const&); diff --git a/src/kranewl/env.cc b/src/kranewl/env.cc @@ -0,0 +1,67 @@ +#include <kranewl/env.hh> + +#include <cctype> +#include <cstdint> +#include <cstdlib> +#include <fstream> +#include <locale> +#include <regex> + +#include <spdlog/spdlog.h> + +static inline std::string +evaluate_value(std::string const& value) +{ + static const std::regex regex(R"(\$([a-zA-Z0-9_]+))"); + + std::string evaluation = {}; + std::smatch match; + + auto it = value.cbegin(); + auto end = value.cend(); + + while (std::regex_search(it, end, match, regex)) { + char const* env = getenv(match.str(1).c_str()); + evaluation += match.prefix(); + evaluation += env ? env : ""; + it = match.suffix().first; + } + + evaluation.append(it, value.cend()); + return evaluation; +} + +void +parse_and_set_env_vars(std::string const& env_path) +{ + struct Assignment_ctype : std::ctype<char> { + Assignment_ctype() + : std::ctype<char>(get_table()) + {} + + static mask const* get_table() + { + static mask rc[table_size]; + rc[static_cast<std::size_t>('=')] = std::ctype_base::space; + rc[static_cast<std::size_t>('\n')] = std::ctype_base::space; + rc[static_cast<std::size_t>('\r')] = std::ctype_base::space; + return &rc[0]; + } + }; + + std::ifstream env_if(env_path); + env_if.imbue(std::locale(env_if.getloc(), new Assignment_ctype)); + + const auto isspace = [](char c) { + return std::isspace(static_cast<unsigned char>(c)); + }; + + std::string var, value; + while (env_if >> var >> value) { + var.erase(std::remove_if(var.begin(), var.end(), isspace), var.end()); + value.erase(std::remove_if(value.begin(), value.end(), isspace), value.end()); + + spdlog::info("Setting environment variable: {}={}", var, value); + setenv(var.c_str(), evaluate_value(value).c_str(), true); + } +}