stamen

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

commit a0f03cd75241bbb601e1b2eb7abbaa392ea9a3d1
parent 4edb0a625526b7b14e16275f2defa4a4a66b83e4
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Thu, 16 Nov 2023 13:08:23 +0000

Small Improvements

* Users are required to set display function at compile time
* Ditched default entry
* Improve the interface

Diffstat:
M.gitignore | 2++
MCMakeLists.txt | 2+-
Mdemo/main.cpp | 6++++--
Minclude/menu.h | 25++++++++++++++++---------
Msrc/generate.cpp | 2++
Msrc/menu.cpp | 9+++++----
6 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,2 +1,4 @@ build .cache +demo/demo_menu.cpp +demo/demo_menu.h diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Menu - VERSION 0.0.5 + VERSION 0.0.6 DESCRIPTION "Experimentation with dinamic menus" LANGUAGES CXX ) diff --git a/demo/main.cpp b/demo/main.cpp @@ -2,6 +2,8 @@ #include "demo_menu.h" +const Menu::display_f Menu::display = Menu::builtinDisplay; + int operation(void) { std::cout << "operation" << std::endl; std::cout << "Some operation is done" << std::endl; @@ -14,10 +16,10 @@ int finish(void) { } int menu_static_run(void) { return menu::menu_main(); } -int menu_dynamic_run(void) { return Menu::start(); } +int menu_dynamic_run(void) { return Menu::start("menu_main"); } int menu_dynamic_print(void) { - Menu::print(); + Menu::print("menu_main"); return 1; } diff --git a/include/menu.h b/include/menu.h @@ -28,18 +28,21 @@ public: }; struct item_t { - const std::string prompt, code; - callback_f callback = nullptr; - - item_t(const std::string &code, const std::string &prompt) - : code(code), prompt(prompt) {} + friend class Menu; item_t(const callback_f func, const std::string &prompt) : callback(func), prompt(prompt) {} + private: int operator()(void) const { return callback ? callback() : getMenu(code)(); } + + item_t(const std::string &code, const std::string &prompt) + : code(code), prompt(prompt) {} + + const std::string prompt, code; + callback_f callback = nullptr; }; static void read(const std::string &s) { @@ -65,19 +68,23 @@ public: } } - static int start() { return getMenu(entry)(); } + static int start(const std::string &entry) { return getMenu(entry)(); } static void insert(const std::string &code, const callback_f callback) { // lookup.emplace(std::piecewise_construct, std::forward_as_tuple(code), // std::forward_as_tuple(code, callback)); lookup.insert({code, Menu(code, callback)}); } - static void print(const std::string &code = entry, const int depth = 1); + static void print(const std::string &entry) { print(entry, 1); } static void generateSource(std::ostream &os); static void generateInclude(std::ostream &os); - static int display(const std::string &name, const item_t items[], int size); + typedef int (*display_f)(const std::string &name, const item_t items[], + std::size_t size); + static const display_f display; + static int builtinDisplay(const std::string &name, const item_t items[], + std::size_t size); int operator()() const { return callback ? callback() : display(title, items.data(), items.size()); @@ -92,8 +99,8 @@ private: typedef std::unordered_map<std::string, Menu> lookup_t; static lookup_t lookup; - static const std::string entry; + static void print(const std::string &entry, const int depth); static const Menu &getMenu(const std::string &code) { const auto it = lookup.find(code); if (it == lookup.end()) throw EMenu(); diff --git a/src/generate.cpp b/src/generate.cpp @@ -1,6 +1,8 @@ #include "menu.h" #include <string> +const Menu::display_f Menu::display = Menu::builtinDisplay; + int main(const int argc, const char *argv[]) { if (argc != 2) { std::cout << "please enter at exaclty one config file" << std::endl; diff --git a/src/menu.cpp b/src/menu.cpp @@ -8,9 +8,9 @@ #include <unordered_set> std::unordered_map<std::string, Menu> Menu::lookup; -const std::string Menu::entry = "menu_main"; -int Menu::display(const std::string &name, const item_t items[], int size) { +int Menu::builtinDisplay(const std::string &name, const item_t items[], + std::size_t size) { int choice; const int digits = std::log10(size) + 1; while (true) { @@ -23,7 +23,7 @@ int Menu::display(const std::string &name, const item_t items[], int size) { std::cout << "Choose an option: "; if (std::cin >> choice && choice >= -1 && choice < size) { if (choice == -1) { - std::cout << "choice: back\n"; + std::cout << "Choice: back\n"; return 1; } @@ -47,6 +47,7 @@ int Menu::display(const std::string &name, const item_t items[], int size) { return 1; } + void Menu::generateInclude(std::ostream &os) { os << "#include \"menu.h\"\n\n"; os << "namespace menu {\n\n"; @@ -85,7 +86,7 @@ void Menu::print(const std::string &code, const int depth) { if (it == lookup.end()) return; const Menu &menu = it->second; - if (depth == 1) { std::cout << std::format("{}({})\n", menu.title, code); } + if (depth == 1) std::cout << std::format("{}({})\n", menu.title, code); if (!menu.callback) { for (const auto &item : menu.items) {