stamen

Static 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; }