commit 08ff305c12bb4a7f9cc10610f51616b096647aa6
parent f4fed18ad7916907f96caaa641143d3ed00f02f6
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Thu, 30 Nov 2023 19:11:48 +0000
Great simplification
* Remove option for creating dynamic menus
* Greatly simplify handling and future extensions
* Simplify C interface
* Get rid of hacky array conversion
* Simplify demo programs
Diffstat:
8 files changed, 38 insertions(+), 116 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stamen
- VERSION 0.0.12
+ VERSION 0.0.13
DESCRIPTION "Static menu generator"
LANGUAGES C CXX
)
diff --git a/demo/main.c b/demo/main.c
@@ -1,8 +1,8 @@
#include "demo_menu.h"
#include "stamenc.h"
+
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
const display_f display = stamen_builtin_display;
@@ -29,37 +29,12 @@ int finish(void) {
exit(0);
}
-int menu_static_run(void) { return menu_main(); }
-int menu_dynamic_run(void) { return stamen_start("menu_main"); }
-
int menu_dynamic_print(void) {
stamen_print("menu_main");
return 1;
}
-int main(int argc, const char *argv[]) {
- const char *filename = "./demo_menu.conf";
- char buffer[FILENAME_MAX] = {0};
- const char *sep = strrchr(argv[0], '/');
- if (sep) {
- const size_t size = sep - argv[0] + 1;
- memcpy(buffer, argv[0], size);
- memcpy(buffer + size, filename, strlen(filename));
- }
-
- stamen_read(sep ? buffer : filename);
- stamen_insert("finish", finish);
- stamen_insert("operation1", operation1);
- stamen_insert("operation2", operation2);
- stamen_insert("operation3", operation3);
-
- static const item_t items[] = {
- { menu_static_run, "Run statically generated menu"},
- { menu_dynamic_run, "Run dynamic menu"},
- {menu_dynamic_print, "Print dynamic menu"},
- { finish, "Quit"},
- };
- display("Menu demo program", items, sizeof(items) / sizeof(item_t));
-
+int main(void) {
+ menu_main();
return 0;
}
diff --git a/demo/main.cpp b/demo/main.cpp
@@ -1,6 +1,7 @@
-#include <iostream>
-
#include "demo_menu.hpp"
+#include "stamen.h"
+
+#include <iostream>
using stamen::Menu;
@@ -31,32 +32,7 @@ int finish(void) {
exit(0);
}
-int menu_static_run(void) { return stamen::menu_main(); }
-int menu_dynamic_run(void) { return Menu::start("menu_main"); }
-
-int menu_dynamic_print(void) {
- Menu::print("menu_main");
- return 1;
-}
-
-int main(int argc, const char *argv[]) {
- std::string name(argv[0]);
- std::string::size_type pos = name.rfind('/');
- std::string base = pos != std::string::npos ? name.substr(0, pos) : ".";
-
- Menu::read(base + "/demo_menu.conf");
- Menu::insert("finish", finish);
- Menu::insert("operation1", operation1);
- Menu::insert("operation2", operation2);
- Menu::insert("operation3", operation3);
-
- static const Menu::item_t items[] = {
- { menu_static_run, "Run statically generated menu"},
- { menu_dynamic_run, "Run dynamic menu"},
- {menu_dynamic_print, "Print dynamic menu"},
- { finish, "Quit"},
- };
- Menu::display("Menu demo program", items,
- sizeof(items) / sizeof(Menu::item_t));
+int main(void) {
+ stamen::menu_main();
return 0;
}
diff --git a/include/stamen.h b/include/stamen.h
@@ -32,41 +32,13 @@ public:
Menu(private_ctor_t, const std::string &code, const callback_f callback)
: Menu(code, callback) {}
- struct item_t {
- item_t() {}
- item_t(const callback_f func, const std::string &prompt)
- : callback(func), prompt(prompt) {}
-
- item_t(const std::string &code, const std::string &prompt)
- : code(code), prompt(prompt) {}
-
- const std::string getCode(void) const { return code; }
- const std::string getPrompt(void) const { return prompt; }
- const callback_f getCallback(void) const { return callback; }
-
- int operator()(void) const { return callback ? callback() : start(code); }
-
- private:
- std::string prompt, code;
- callback_f callback = nullptr;
- };
-
- typedef int (*display_f)(const std::string &, const item_t[], std::size_t);
+ typedef int (*display_f)(const std::string &, const ::item_t[], std::size_t);
static const display_f display;
static void read(const std::string &s);
static void insert(const std::string &code, const callback_f callback);
static void print(const std::string &entry) { print(entry, 1); }
- static int start(const std::string &entry) {
- const Menu *menu = getMenu(entry);
- if (!menu) return 1;
- return menu->operator()();
- }
-
- int operator()() const {
- return callback ? callback() : display(title, items.data(), items.size());
- }
private:
Menu(const std::string &code, const std::string &prompt)
@@ -92,7 +64,14 @@ private:
const std::string code, title;
const callback_f callback = nullptr;
- std::vector<item_t> items;
+
+ struct lookup_item_t {
+ lookup_item_t(const std::string &code, const std::string &prompt)
+ : code(code), prompt(prompt) {}
+ const std::string code, prompt;
+ };
+
+ std::vector<lookup_item_t> items;
};
inline void Menu::read(const std::string &s) {
@@ -132,13 +111,13 @@ inline void Menu::print(const std::string &code, const int depth) {
if (!menu->callback) {
for (const auto &item : menu->items) {
std::cout << std::format("{}{} ({})\n", std::string(depth << 1, ' '),
- item.getPrompt(), item.getCode());
- menu->print(item.getCode(), depth + 1);
+ item.prompt, item.code);
+ menu->print(item.code, depth + 1);
}
}
}
-int builtinDisplay(const std::string &title, const Menu::item_t items[],
+int builtinDisplay(const std::string &title, const ::item_t items[],
std::size_t size);
} // namespace stamen
diff --git a/include/stamenc.h b/include/stamenc.h
@@ -20,7 +20,6 @@ extern const display_f display;
EXTERNC void stamen_read(const char *file);
EXTERNC void stamen_print(const char *entry);
-EXTERNC int stamen_start(const char *entry);
EXTERNC void stamen_insert(const char *code, callback_f callback);
EXTERNC int stamen_builtin_display(const char *title, const item_t items[], int size);
diff --git a/src/generate.cpp b/src/generate.cpp
@@ -16,7 +16,6 @@ public:
static void generateInclude(std::ostream &os, bool cpp) {
os << "#ifndef STAMEN_MENU_H\n";
os << "#define STAMEN_MENU_H\n\n";
- os << std::format("#include <stamen{}.h>\n\n", !cpp ? "c" : "");
if (cpp) os << "namespace stamen {\n\n";
for (const auto &[code, _] : Menu::getLookup()) {
const Menu *menu = Menu::getMenu(code);
@@ -25,7 +24,7 @@ public:
os << std::format("int {}(void);\n", menu->code);
}
if (cpp) os << "\n}\n";
- os << "#endif\n";
+ os << "\n#endif\n";
}
static void generateSource(std::ostream &os, bool cpp) {
@@ -38,15 +37,13 @@ public:
if (menu->callback) continue;
os << std::format("int {}(void) {{\n", menu->code);
- os << std::format("\tstatic const {}item_t items[] = {{\n",
- cpp ? "Menu::" : "");
+ os << std::format("\tstatic const item_t items[] = {{\n");
for (const auto &item : menu->items) {
- os << std::format("\t\t{{ {}, \"{}\" }},\n", item.getCode(),
- item.getPrompt());
+ os << std::format("\t\t{{ {}, \"{}\" }},\n", item.code, item.prompt);
}
os << std::format("\t}};\n");
- os << std::format("\treturn {0}display(\"{1}\", items, "
- "sizeof(items) / sizeof({0}item_t));\n",
+ os << std::format("\treturn {}display(\"{}\", items, "
+ "sizeof(items) / sizeof(item_t));\n",
cpp ? "Menu::" : "", menu->title);
os << std::format("}}\n\n");
}
diff --git a/src/stamen.cpp b/src/stamen.cpp
@@ -3,17 +3,19 @@
#include <format>
#include <iostream>
#include <ostream>
+#include <variant>
namespace stamen {
-int builtinDisplay(const std::string &title, const Menu::item_t items[],
+int builtinDisplay(const std::string &title, const ::item_t items[],
std::size_t size) {
int choice;
const int digits = std::log10(size) + 1;
+
while (true) {
std::cout << std::format("{}:\n", title);
for (auto i = 0ul; i < size; i++) {
- std::cout << std::format(" {:{}}. {}\n", i, digits, items[i].getPrompt());
+ std::cout << std::format(" {:{}}. {}\n", i, digits, items[i].prompt);
}
while (true) {
@@ -24,11 +26,12 @@ int builtinDisplay(const std::string &title, const Menu::item_t items[],
return 1;
}
- const Menu::item_t &chosen = items[choice];
- std::cout << std::format("Choice: {}\n\n", chosen.getPrompt());
- const int res = chosen();
- if (res > 1) return res - 1;
- else break;
+ std::cout << std::format("Choice: {}\n\n", items[choice].prompt);
+ const int res = items[choice].callback();
+ if (res > 1)
+ return res - 1;
+ else
+ break;
} else if (std::cin.eof()) {
std::cerr << "encountered end of input!\n";
diff --git a/src/stamenc.cpp b/src/stamenc.cpp
@@ -1,4 +1,5 @@
#include "../include/stamen.h"
+#include "../include/stamenc.h"
using namespace stamen;
@@ -6,18 +7,10 @@ const Menu::display_f Menu::display = nullptr;
void stamen_read(const char *file) { stamen::Menu::read(file); }
void stamen_print(const char *entry) { stamen::Menu::print(entry); }
-int stamen_start(const char *entry) { return stamen::Menu::start(entry); }
void stamen_insert(const char *code, callback_f callback) {
Menu::insert(code, callback);
}
int stamen_builtin_display(const char *title, const item_t items[], int size) {
- Menu::item_t *litems = new Menu::item_t[size];
- if (!litems) return -1;
- for (int i = 0; i < size; i++) {
- litems[i] = Menu::item_t(items[i].callback, items[i].prompt);
- }
- const int ret = builtinDisplay(title, litems, size);
- delete[] litems;
- return ret;
+ return builtinDisplay(title, items, size);
}