cemplate

Simple C++ template engine
git clone git://git.dimitrijedobrota.com/cemplate.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit 51cc42e95b4ed60855abf0b74cf22fc1fb8a4c8f
parent 9c7f4ab5de0c9e4042a356a239bb497537b22061
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Sun, 23 Feb 2025 15:54:19 +0100

Handle indent; Add initlist, decl, string

Diffstat:
M .clang-tidy | +
M CMakeLists.txt | + -
M example/example.cpp | ++++
M include/cemplate/cemplate.hpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -----
M source/cemplate.cpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ----------------

5 files changed, 140 insertions(+), 23 deletions(-)


diff --git a/ .clang-tidy b/ .clang-tidy

@@ -18,6 +18,7 @@ Checks: "*,\ -modernize-use-ranges,\ -modernize-use-trailing-return-type,\ -misc-include-cleaner,\
-misc-no-recursion,\
" WarningsAsErrors: '' CheckOptions:

diff --git a/ CMakeLists.txt b/ CMakeLists.txt

@@ -4,7 +4,7 @@ include(cmake/prelude.cmake) project( cemplate
VERSION 0.1.5
VERSION 0.1.6
DESCRIPTION "Simple C++ template engine" HOMEPAGE_URL "https://git.dimitrijedobrota.com/cemplate.git" LANGUAGES CXX

diff --git a/ example/example.cpp b/ example/example.cpp

@@ -23,6 +23,10 @@ int main() std::cout << func("test"); std::cout << func_decl("decl", "void", {});
std::cout << '\n';
std::cout << "static const test_class test = ";
std::cout << initlist({"val11", "val12", {"val21", "val22"}, "val13"});
std::cout << nspace("cemplate");

diff --git a/ include/cemplate/cemplate.hpp b/ include/cemplate/cemplate.hpp

@@ -1,11 +1,68 @@ #pragma once
#include <cstdint>
#include <string>
#include <variant>
#include <vector> namespace cemplate {
struct param_t
{
std::string type;
std::string name;
};
struct initlist_elem;
struct initlist
{
std::string format(std::uint64_t lvl) const;
friend std::ostream& operator<<(std::ostream& ost, const initlist& list);
template<typename... Args>
void emplace_back(Args... args)
{
values.emplace_back(std::forward<Args>(args)...);
}
std::vector<initlist_elem> values; // NOLINT
};
struct initlist_elem
{
initlist_elem(std::string value) // NOLINT
: m_value(std::move(value))
{
}
initlist_elem(std::string_view value) // NOLINT
: m_value(std::in_place_type<std::string>, value)
{
}
initlist_elem(const char* value) // NOLINT
: m_value(value)
{
}
initlist_elem(std::initializer_list<initlist_elem> list) // NOLINT
: m_value(std::in_place_type<initlist>, list)
{
}
initlist_elem(initlist list) // NOLINT
: m_value(std::move(list))
{
}
const auto& value() const { return m_value; }
private:
std::variant<std::string, initlist> m_value;
};
std::string pragma_once(); std::string include(const std::string& header, bool local = false);

@@ -14,11 +71,9 @@ std::string nspace(const std::string& name); std::string ret(const std::string& val);
struct param_t
{
std::string type;
std::string name;
};
std::string string(const std::string& string);
std::string decl(const std::string& type, const std::string& name);
std::string func(const std::string& name, const std::string& ret = "",

diff --git a/ source/cemplate.cpp b/ source/cemplate.cpp

@@ -1,4 +1,5 @@ #include <format>
#include <functional>
#include <iostream> #include <stack> #include <unordered_set>

@@ -8,6 +9,13 @@ namespace {
static std::uint64_t indent_lvl = 0; // NOLINT
auto indent(std::uint64_t lvl = indent_lvl)
{
return std::string(lvl * 2, ' ');
}
void warning(const std::string& message, const std::string& addition) // NOLINT { std::cerr << "Warning: " << message;

@@ -17,13 +25,28 @@ void warning(const std::string& message, const std::string& addition) // NOLINT std::cerr << '\n' << std::flush; }
template<typename T>
std::string accumulate(const std::vector<T>& values,
const std::function<std::string(const T&)>& format,
const std::string& delim)
{
std::string res;
if (!values.empty()) {
res += format(values[0]);
for (std::size_t i = 1; i < values.size(); i++) {
res += delim + format(values[i]);
}
}
return res;
}
} // namespace namespace cemplate {
static std::uint32_t indent = 0; // NOLINT
std::string pragma_once() { return "#pragma once\n\n";

@@ -58,30 +81,62 @@ std::string nspace(const std::string& name) std::string ret(const std::string& val) {
return std::format("return {};\n", val);
return std::format("{}return {};\n", indent(), val);
}
std::string func_helper(const std::string& name,
const std::string& ret,
const std::vector<param_t>& params)
std::string string(const std::string& string)
{
static const auto format = [](const param_t& param)
{ return param.name.empty() ? param.type : param.type + ' ' + param.name; };
return std::format(R"("{}")", string);
}
std::string decl(const std::string& type, const std::string& name)
{
return std::format("{}{} {} = ", indent(), type, name);
}
std::string eval(const std::string& val, std::uint64_t lvl); // NOLINT
std::string eval(const initlist& list, std::uint64_t lvl); // NOLINT
std::string initlist::format(uint64_t lvl) const
{
std::string res;
res += ret + ' ';
res += name + '(';
if (!params.empty()) {
res += format(params[0]);
for (std::size_t i = 1; i < params.size(); i++) {
res += ", " + format(params[i]);
}
for (const auto& node : values) {
std::visit([&](const auto& value) { res += eval(value, lvl + 1); },
node.value());
} return res; }
std::string eval(const initlist& list, std::uint64_t lvl)
{
return std::format(
"{}{{\n{}{}}},\n", indent(lvl), list.format(lvl + 1), indent(lvl));
}
std::string eval(const std::string& val, std::uint64_t lvl)
{
return std::format("{}{},\n", indent(lvl), val);
}
std::ostream& operator<<(std::ostream& ost, const initlist& list)
{
return ost << std::format(
"{{\n{}{}}};\n", list.format(indent_lvl + 1), indent());
}
std::string func_helper(const std::string& name, // NOLINT
const std::string& ret,
const std::vector<param_t>& params)
{
static const auto format = [](const param_t& param)
{ return param.name.empty() ? param.type : param.type + ' ' + param.name; };
return std::format(
"{} {}({})", ret, name, accumulate<param_t>(params, format, ", "));
}
std::string func(const std::string& name, const std::string& ret, const std::vector<param_t>& params)

@@ -94,7 +149,8 @@ std::string func(const std::string& name, } last = name;
return func_helper(name, ret, params) + ") {\n";
indent_lvl++;
return func_helper(name, ret, params) + " {\n";
} if (last != name) {

@@ -102,6 +158,7 @@ std::string func(const std::string& name, } last.clear();
indent_lvl--;
return "}\n\n"; }

@@ -109,7 +166,7 @@ std::string func_decl(const std::string& name, const std::string& ret, const std::vector<param_t>& params) {
return func_helper(name, ret, params) + ");\n";
return func_helper(name, ret, params) + ";\n";
} } // namespace cemplate