stamen

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

commit c169c53c39af25c773ebbbe13567cc32ffbd3e37
parent e814fd0a34a1f28773e3551a76a341704fcc63e4
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Sun, 23 Feb 2025 17:56:27 +0100

Improve consistency

Diffstat:
M example/CMakeLists.txt | -
M example/dynamic.cpp | +++++ -----
D example/shared.h | -----------
M include/stamen/stamen.hpp | ++++++ ------------
M source/generate.cpp | +++++++ ------
M source/stamen.cpp | +++++++ --------

6 files changed, 25 insertions(+), 43 deletions(-)


diff --git a/ example/CMakeLists.txt b/ example/CMakeLists.txt

@@ -9,7 +9,6 @@ if(PROJECT_IS_TOP_LEVEL) endif() configure_file(demo_menu.conf demo_menu.conf COPYONLY)
configure_file(shared.h shared.h COPYONLY)
add_custom_target(run-examples)

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

@@ -19,8 +19,7 @@ int display(const stamen::menu_t& menu) std::cout << std::format("{}:\n", menu.title()); for (auto i = 0UL; i < menu.items().size(); i++) {
std::cout << std::format(
" {:{}}. {}\n", i, dgts, menu.items()[i].prompt);
std::cout << std::format(" {:{}}. {}\n", i, dgts, menu.item(i).prompt);
} while (true)

@@ -35,8 +34,8 @@ int display(const stamen::menu_t& menu) } const auto uchoice = static_cast<size_t>(choice);
std::cout << "Choice: " << menu.items()[uchoice].prompt << "\n\n";
const int res = menu.items()[uchoice].callback(uchoice);
std::cout << "Choice: " << menu.item(uchoice).prompt << "\n\n";
const int res = menu.item(uchoice).callback(uchoice);
if (res < 2) break; return res - 1;

@@ -61,7 +60,8 @@ int display(const stamen::menu_t& menu) int finish(std::size_t /* unused */) {
exit(0); // NOLINT
// return from everything so that memory can be freed
return 1000;
} int operation1(std::size_t /* unused */)

diff --git a/ example/shared.h b/ example/shared.h

@@ -1,11 +0,0 @@
#ifndef STAMEN_DEMO_SHARED_H
#define STAMEN_DEMO_SHARED_H
#include <stddef.h> // NOLINT
int finish(size_t);
int operation1(size_t);
int operation2(size_t);
int operation3(size_t);
#endif

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

@@ -15,8 +15,9 @@ using display_f = std::function<int(const menu_t&)>; struct item_t {
callback_f callback;
std::string code;
std::string prompt;
callback_f callback;
}; // NOLINTBEGIN

@@ -56,13 +57,13 @@ public: const std::string& code() const { return m_code; } const std::string& title() const { return m_title; }
std::size_t size() const { return m_items.size(); }
const item_t& item(std::size_t idx) const { return m_items[idx]; }
item_t& item(std::size_t idx) { return m_items[idx]; }
const auto& items() const { return m_items; } auto& items() { return m_items; }
auto get_callback(std::size_t idx) const { return m_items[idx].callback; }
const auto& get_code(std::size_t idx) const { return m_codes[idx].code; }
const auto& get_prompt(std::size_t idx) const { return m_codes[idx].prompt; }
private: menu_t(std::string code, std::string prompt) : m_code(std::move(code))

@@ -74,15 +75,8 @@ private: const std::string& prompt, const callback_f& callback = display_stub);
struct code_t
{
std::string code;
std::string prompt;
};
std::string m_code; std::string m_title;
std::vector<code_t> m_codes;
std::vector<item_t> m_items; };

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

@@ -21,11 +21,11 @@ auto accumulate_items(const stamen::menu_t& lmenu) using namespace cemplate; // NOLINT initlist items;
for (auto i = 0UL; i < lmenu.items().size(); i++)
for (const auto& [code, prompt, _] : lmenu.items())
{ items.emplace_back(initlist({
string(lmenu.get_prompt(i)),
lmenu.get_code(i),
string(prompt),
code,
})); }

@@ -47,10 +47,13 @@ void generate_include(std::ostream& ost, const arguments_t& args) ost << nspace(args.nspace); ost << R"(
struct menu_t
class menu_t
{
public:
using callback_f = std::function<int(std::size_t)>;
static int visit(const menu_t& menu);
struct item_t { std::string prompt;

@@ -60,8 +63,6 @@ struct menu_t std::string title; callback_f callback; std::vector<item_t> items;
static int visit(const menu_t& menu);
}; )";

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

@@ -69,7 +69,7 @@ void insert(const char* code, const callback_f& callback) std::cout << "Stamen: unknown callback registration...\n" << std::flush; return; }
free_lookup.emplace(code, callback);
itr->second = callback;
} int dynamic(const char* code, const display_f& disp)

@@ -84,7 +84,7 @@ int display_stub(std::size_t idx) static std::deque<const menu_t*> stack; const std::string& code =
!stack.empty() ? stack.back()->get_code(idx) : display_stub_default;
!stack.empty() ? stack.back()->item(idx).code : display_stub_default;
const auto ml_it = menu_lookup.find(code); if (ml_it != menu_lookup.end())

@@ -97,7 +97,10 @@ int display_stub(std::size_t idx) } const auto fl_it = free_lookup.find(code);
if (fl_it != free_lookup.end()) return fl_it->second(0);
if (fl_it != free_lookup.end() && fl_it->second != nullptr)
{
return fl_it->second(0);
}
std::cout << "Stamen: nothing to do...\n" << std::flush; return 1;

@@ -107,11 +110,7 @@ void menu_t::insert(const std::string& code, const std::string& prompt, const callback_f& callback) {
char* buffer = new char[prompt.size() + 1]; // NOLINT
strcpy(buffer, prompt.c_str()); // NOLINT
m_items.emplace_back(callback, buffer);
m_codes.emplace_back(code, prompt);
m_items.emplace_back(code, prompt, callback);
} } // namespace stamen