stamenStatic Menu Generator |
git clone git://git.dimitrijedobrota.com/stamen.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 327abb09023582d7a9310440fd011cf012ae4195 |
parent | 12c5ce88ce059481256dc028f9c672c1861655ca |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Thu, 13 Jun 2024 23:15:43 +0200 |
Option to include system or user stamen header
Diffstat:M | demo/CMakeLists.txt | | | ++-- |
M | include/menu.h | | | +++++------ |
M | src/generate.cpp | | | ++++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
3 files changed, 58 insertions(+), 56 deletions(-)
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt
@@ -4,7 +4,7 @@ configure_file(demo_menu.conf ${GENERATE_OUT}/demo_menu.conf COPYONLY)
add_custom_command(
OUTPUT ${GENERATE_OUT}/demo_menu.hpp ${GENERATE_OUT}/demo_menu.cpp
COMMAND ${GENERATE_OUT}/stamen-generate --cpp ${GENERATE_OUT}/demo_menu.conf
COMMAND ${GENERATE_OUT}/stamen-generate --user --cpp ${GENERATE_OUT}/demo_menu.conf
DEPENDS demo_menu.conf stamen-generate
COMMENT "Generating menu files"
)
@@ -23,7 +23,7 @@ set_target_properties(demo PROPERTIES
add_custom_command(
OUTPUT ${GENERATE_OUT}/demo_menu.h ${GENERATE_OUT}/demo_menu.c
COMMAND ${GENERATE_OUT}/stamen-generate --c ${GENERATE_OUT}/demo_menu.conf
COMMAND ${GENERATE_OUT}/stamen-generate --user --c ${GENERATE_OUT}/demo_menu.conf
DEPENDS demo_menu.conf stamen-generate
COMMENT "Generating cmenu files"
)
diff --git a/include/menu.h b/include/menu.h
@@ -12,12 +12,6 @@
namespace stamen {
class Menu {
friend class Generator;
static std::unordered_map<std::string, Menu> menu_lookup;
static std::unordered_map<std::string, callback_f> free_lookup;
static std::string display_stub_default;
struct private_ctor_t {};
public:
@@ -59,6 +53,8 @@ class Menu {
return entries.items[idx].callback;
}
static std::unordered_map<std::string, Menu> menu_lookup;
private:
Menu(std::string code, std::string prompt)
: code(std::move(code)), title(std::move(prompt)) {}
@@ -93,6 +89,9 @@ class Menu {
const std::string code, title;
Entries entries;
static std::unordered_map<std::string, callback_f> free_lookup;
static std::string display_stub_default;
};
} // namespace stamen
diff --git a/src/generate.cpp b/src/generate.cpp
@@ -8,63 +8,65 @@
#include <iostream>
#include <string>
namespace stamen {
const stamen_display_f stamen_display = stamen::builtin_display;
class Generator {
public:
static void generateInclude(std::ostream &os, bool cpp) {
os << "#ifndef STAMEN_MENU_H\n";
os << "#define STAMEN_MENU_H\n\n";
struct arguments_t {
std::string config;
bool cpp = false;
bool user = false;
} opt;
if (cpp) os << "#include \"stamen.hpp\"\n\n";
void generateIncludeHeaders(std::ostream &os) {
if (opt.user) {
if (opt.cpp) os << "#include \"stamen.hpp\"\n\n";
else os << "#include \"stamen.h\"\n\n";
} else {
if (opt.cpp) os << "#include <stamen/stamen.hpp>\n\n";
else os << "#include <stamen/stamen.h>\n\n";
}
}
for (const auto &[code, menu] : Menu::menu_lookup) {
os << std::format("int {}(int);\n", menu.getCode());
}
void generateInclude(std::ostream &os) {
os << "#ifndef STAMEN_MENU_H\n";
os << "#define STAMEN_MENU_H\n\n";
os << "\n#endif\n";
}
generateIncludeHeaders(os);
static void generateSource(std::ostream &os, bool cpp) {
if (cpp) os << "#include \"stamen.hpp\"\n\n";
else os << "#include \"stamen.h\"\n\n";
for (const auto &[code, menu] : stamen::Menu::menu_lookup) {
os << std::format("int {}(int);\n", menu.getCode());
}
os << "#include \"shared.h\"\n\n";
for (const auto &[code, menu] : Menu::menu_lookup) {
os << std::format("int {}(int) {{\n", menu.getCode());
os << "\n#endif\n";
}
if (cpp) os << "\tstatic const stamen::item_t items[] = ";
else os << "\tstatic const stamen_item_t items[] = ";
void generateSource(std::ostream &os) {
os << "#include \"shared.h\"\n";
generateIncludeHeaders(os);
os << "{\n";
for (int i = 0; i < menu.getSize(); i++) {
os << "\t\t{ " << menu.getCode(i);
os << ", \"" << menu.getPrompt(i) << "\" },\n";
}
os << "\t};\n";
for (const auto &[code, menu] : stamen::Menu::menu_lookup) {
os << std::format("int {}(int) {{\n", menu.getCode());
if (cpp) os << "\treturn stamen::stamen_display";
else os << "\treturn stamen_display";
if (opt.cpp) os << "\tstatic const stamen::item_t items[] = ";
else os << "\tstatic const stamen_item_t items[] = ";
os << std::format("(\"{}\"", menu.getTitle());
os << ", items, sizeof(items) / sizeof(items[0]));\n";
os << "}\n\n";
os << "{\n";
for (int i = 0; i < menu.getSize(); i++) {
os << "\t\t{ " << menu.getCode(i);
os << ", \"" << menu.getPrompt(i) << "\" },\n";
}
}
};
} // namespace stamen
os << "\t};\n";
struct arguments_t {
std::string config;
bool cpp = false;
};
if (opt.cpp) os << "\treturn stamen::stamen_display";
else os << "\treturn stamen_display";
os << std::format("(\"{}\"", menu.getTitle());
os << ", items, sizeof(items) / sizeof(items[0]));\n";
os << "}\n\n";
}
}
int parse_opt(int key, const char *arg, args::Parser *parser) {
auto arguments = (arguments_t *)parser->input();
switch (key) {
case 'u': arguments->user = true; break;
case 666: arguments->cpp = false; break;
case 777: arguments->cpp = true; break;
case args::ARG:
@@ -84,6 +86,8 @@ static const args::option_t options[]{
{0, 0, 0, 0, "Output mode", 1},
{"c", 666, 0, 0, "Generate files for C"},
{"cpp", 777, 0, 0, "Generate files for C++"},
{0, 0, 0, 0, "Output settings", 2},
{"user", 'u', 0, 0, "Include user stamen headers"},
{0, 0, 0, 0, "Informational Options", -1},
{0},
};
@@ -96,23 +100,22 @@ static const args::argp_t argp{
};
int main(int argc, char *argv[]) {
arguments_t arguments;
if (args::parse(&argp, argc, argv, 0, &arguments)) {
if (args::parse(&argp, argc, argv, 0, &opt)) {
std::cerr << "There was an error while parsing arguments";
return 0;
}
const auto &config = arguments.config;
const auto &config = opt.config;
stamen::Menu::read(config);
std::string::size_type pos = arguments.config.rfind('.');
std::string::size_type pos = opt.config.rfind('.');
std::string base =
pos != std::string::npos ? config.substr(0, pos) : config;
std::string ext = arguments.cpp ? "pp" : "";
std::string ext = opt.cpp ? "pp" : "";
std::ofstream source(base + ".c" + ext), include(base + ".h" + ext);
stamen::Generator::generateSource(source, arguments.cpp);
stamen::Generator::generateInclude(include, arguments.cpp);
generateInclude(include);
generateSource(source);
return 0;
}