stamen

Static Menu Generator
git clone git://git.dimitrijedobrota.com/stamen.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit 8fe2a8b55ac5c587ad03da22c3e5cc080b7e5687
parent 327abb09023582d7a9310440fd011cf012ae4195
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Thu, 13 Jun 2024 23:53:18 +0200

No more stamen_display * In dynamic mode pass display function when starting * stamen-generate now takes display function name as an option * Improve code consistency

Diffstat:
M demo/CMakeLists.txt | + -
M demo/dynamic.cpp | + -----
M demo/main.c | ----
M demo/main.cpp | ---
M include/menu.h | ++++ --
M include/stamen.h | + --
M include/stamen.hpp | + -
M src/c_bindings.cpp | ++++ --
M src/generate.cpp | ++++++++++++++ ----
M src/menu.cpp | ++ -
M src/stamen.cpp | +++++ ----

11 files changed, 33 insertions(+), 29 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 --user --cpp ${GENERATE_OUT}/demo_menu.conf
COMMAND ${GENERATE_OUT}/stamen-generate --user -d test_display --cpp ${GENERATE_OUT}/demo_menu.conf
DEPENDS demo_menu.conf stamen-generate COMMENT "Generating menu files" )

diff --git a/ demo/dynamic.cpp b/ demo/dynamic.cpp

@@ -1,10 +1,6 @@ #include "stamen.hpp" #include <iostream>
// still need to link against stamen library
// as builtin_display is being used
// because there is no override
int finish(int) { exit(1); } int operation1(int) {

@@ -33,6 +29,6 @@ int main() { stamen::insert("operation3", operation3); // start the menu on specific panel
stamen::dynamic("menu_main");
stamen::dynamic("menu_main", stamen::builtin_display);
return 0; }

diff --git a/ demo/main.c b/ demo/main.c

@@ -4,10 +4,6 @@ #include <stdio.h> #include <stdlib.h>
// need to link against stamen library
// in order to use stamen_builtin_display
const stamen_display_f stamen_display = stamen_builtin_display;
int operation1(void) { printf("operation 1\n"); printf("Some operation is done\n");

diff --git a/ demo/main.cpp b/ demo/main.cpp

@@ -12,9 +12,6 @@ int test_display(const char *title, const stamen::item_t itemv[], int size) { return 0; }
// no need to link against stamen library as custom display is provided
const stamen::display_f stamen::stamen_display = test_display;
int operation1(int) { std::cout << "operation 1" << std::endl; std::cout << "Some operation is done" << std::endl;

diff --git a/ include/menu.h b/ include/menu.h

@@ -22,8 +22,9 @@ class Menu { Menu(const Menu &) = delete; Menu &operator=(const Menu &) = delete;
static int dynamic(const std::string &code) {
display_stub_default = code;
static int dynamic(const std::string &code, display_f display) {
Menu::display_stub_default = code;
Menu::display = display;
return display_stub(-1); };

@@ -92,6 +93,7 @@ class Menu { static std::unordered_map<std::string, callback_f> free_lookup; static std::string display_stub_default;
static display_f display;
}; } // namespace stamen

diff --git a/ include/stamen.h b/ include/stamen.h

@@ -15,14 +15,13 @@ struct stamen_item_t { }; typedef int (*stamen_display_f)(const char *, const stamen_item_t[], int);
extern const stamen_display_f stamen_display;
#if !defined __cplusplus || defined WITH_C_BINDINGS void stamen_read(const char *filename); void stamen_insert(const char *code, stamen_callback_f callback);
int stamen_dynamic(const char *code);
int stamen_dynamic(const char *code, stamen_display_f display);
int stamen_builtin_display(const char *title, const stamen_item_t itemv[], int size);

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

@@ -12,7 +12,7 @@ using item_t = stamen_item_t; void read(const char *filename); void insert(const char *code, callback_f callback);
int dynamic(const char *code);
int dynamic(const char *code, display_f display);
int builtin_display(const char *title, const item_t itemv[], int size); } // namespace stamen

diff --git a/ src/c_bindings.cpp b/ src/c_bindings.cpp

@@ -3,14 +3,16 @@ namespace stamen {
int stamen_dynamic(const char *code) { return dynamic(code); }
void stamen_read(const char *filename) { return read(filename); } void stamen_insert(const char *code, stamen_callback_f callback) { return insert(code, callback); }
int stamen_dynamic(const char *code, stamen_display_f display) {
return dynamic(code, display);
}
int stamen_builtin_display(const char *title, const stamen_item_t itemv[], int size) { return builtin_display(title, itemv, size);

diff --git a/ src/generate.cpp b/ src/generate.cpp

@@ -10,6 +10,7 @@ struct arguments_t { std::string config;
std::string display;
bool cpp = false; bool user = false; } opt;

@@ -41,6 +42,10 @@ void generateSource(std::ostream &os) { os << "#include \"shared.h\"\n"; generateIncludeHeaders(os);
os << std::format("extern int {}(const char *title, ", opt.display);
if (opt.cpp) os << "const stamen::item_t itemv[], int size);\n\n";
else os << "const stamen_item_t itemv[], int size);\n\n";
for (const auto &[code, menu] : stamen::Menu::menu_lookup) { os << std::format("int {}(int) {{\n", menu.getCode());

@@ -54,10 +59,7 @@ void generateSource(std::ostream &os) { } os << "\t};\n";
if (opt.cpp) os << "\treturn stamen::stamen_display";
else os << "\treturn stamen_display";
os << std::format("(\"{}\"", menu.getTitle());
os << std::format("\treturn {}(\"{}\"", opt.display, menu.getTitle());
os << ", items, sizeof(items) / sizeof(items[0]));\n"; os << "}\n\n"; }

@@ -67,6 +69,7 @@ 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 'd': arguments->display = arg; break;
case 666: arguments->cpp = false; break; case 777: arguments->cpp = true; break; case args::ARG:

@@ -78,6 +81,12 @@ int parse_opt(int key, const char *arg, args::Parser *parser) { case args::NO_ARGS: args::failure(parser, 0, 0, "Missing an argument"); args::help(parser, stderr, args::STD_USAGE);
case args::END:
if (arguments->display.empty()) {
if (arguments->cpp) arguments->display = "stamen::builtin_display";
else arguments->display = "stamen_builtin_display";
}
break;
} return 0; }

@@ -87,6 +96,7 @@ static const args::option_t options[]{ {"c", 666, 0, 0, "Generate files for C"}, {"cpp", 777, 0, 0, "Generate files for C++"}, {0, 0, 0, 0, "Output settings", 2},
{"display", 'd', "FUNC", 0, "Set display function to be called"},
{"user", 'u', 0, 0, "Include user stamen headers"}, {0, 0, 0, 0, "Informational Options", -1}, {0},

diff --git a/ src/menu.cpp b/ src/menu.cpp

@@ -13,6 +13,7 @@ namespace stamen { std::unordered_map<std::string, Menu> Menu::menu_lookup; std::unordered_map<std::string, callback_f> Menu::free_lookup; std::string Menu::display_stub_default;
display_f Menu::display;
void Menu::read(const std::string &s) { std::string line, delim, code, prompt;

@@ -61,7 +62,7 @@ int Menu::display_stub(int idx) { if (ml_it != menu_lookup.end()) { const Menu &menu = ml_it->second; st.push_back(&menu);
int ret = stamen_display(menu.title.c_str(), menu.getItemv(), menu.getSize());
int ret = display(menu.title.c_str(), menu.getItemv(), menu.getSize());
st.pop_back(); return ret; }

diff --git a/ src/stamen.cpp b/ src/stamen.cpp

@@ -10,15 +10,16 @@ namespace stamen {
__attribute__((weak))
extern const stamen_display_f stamen_display = stamen_builtin_display;
int dynamic(const char *code) { return Menu::dynamic(code); }
void read(const char *filename) { Menu::read(filename); }
void insert(const char *code, callback_f callback) { Menu::insert(code, callback); }
int dynamic(const char *code, display_f display) {
return Menu::dynamic(code, display);
}
int builtin_display(const char *title, const item_t itemv[], int size) { const size_t digits = size_t(std::log10(size)) + 1; const auto items = std::span(itemv, size_t(size));