stamen

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

commitc169c53c39af25c773ebbbe13567cc32ffbd3e37
parente814fd0a34a1f28773e3551a76a341704fcc63e4
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateSun, 23 Feb 2025 17:56:27 +0100

Improve consistency

Diffstat:
Mexample/CMakeLists.txt|-
Mexample/dynamic.cpp|+++++-----
Dexample/shared.h|-----------
Minclude/stamen/stamen.hpp|++++++------------
Msource/generate.cpp|+++++++------
Msource/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