stamen

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

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 | ++
M CMakeLists.txt | + -
M demo/main.cpp | ++++ --
M include/menu.h | ++++++++++++++++ ---------
M src/generate.cpp | ++
M src/menu.cpp | +++++ ----

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) {