stamen

Stamen - static menu generator
git clone git://git.dimitrijedobrota.com/stamen.git
Log | Files | Refs | README | LICENSE

commit 8fe2a8b55ac5c587ad03da22c3e5cc080b7e5687
parent 327abb09023582d7a9310440fd011cf012ae4195
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Fri, 14 Jun 2024 01: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:
Mdemo/CMakeLists.txt | 2+-
Mdemo/dynamic.cpp | 6+-----
Mdemo/main.c | 4----
Mdemo/main.cpp | 3---
Minclude/menu.h | 6++++--
Minclude/stamen.h | 3+--
Minclude/stamen.hpp | 2+-
Msrc/c_bindings.cpp | 6++++--
Msrc/generate.cpp | 18++++++++++++++----
Msrc/menu.cpp | 3++-
Msrc/stamen.cpp | 9+++++----
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));