stamen

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

commit d5a343ef60d087a9e9ed648a14478f491ffe5a56
parent 08ff305c12bb4a7f9cc10610f51616b096647aa6
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Thu, 30 Nov 2023 19:32:28 +0000

Improve naming, consistency and decomposition

Diffstat:
M CMakeLists.txt | + -
M demo/main.c | + -
M demo/main.cpp | + ---
A include/shared.h | +++++++++++++++
M include/stamen.h | ++++++++++++++ ----------------------
M include/stamenc.h | +++ ------------
M src/generate.cpp | +++++++++ -------
M src/stamen.cpp | ++ ---
M src/stamenc.cpp | ++ ----

9 files changed, 48 insertions(+), 53 deletions(-)


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

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stamen
VERSION 0.0.13
VERSION 0.0.14
DESCRIPTION "Static menu generator" LANGUAGES C CXX )

diff --git a/ demo/main.c b/ demo/main.c

@@ -4,7 +4,7 @@ #include <stdio.h> #include <stdlib.h>
const display_f display = stamen_builtin_display;
const stamen_display_f stamen_display = stamen_builtin_display;
int operation1(void) { printf("operation 1\n");

diff --git a/ demo/main.cpp b/ demo/main.cpp

@@ -3,11 +3,9 @@ #include <iostream>
using stamen::Menu;
// need to link against stamen library // in order to use stamen::BuiltinDisplay
const Menu::display_f Menu::display = stamen::builtinDisplay;
const stamen_display_f stamen_display = stamen::builtinDisplay;
int operation1(void) { std::cout << "operation 1" << std::endl;

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

@@ -0,0 +1,15 @@
#ifndef STAMEN_SHARED_H
#define STAMEN_SHARED_H
typedef int (*stamen_callback_f)(void);
typedef struct item_t item_t;
struct item_t {
stamen_callback_f callback;
const char *prompt;
};
typedef int (*stamen_display_f)(const char *, const item_t[], int);
extern const stamen_display_f stamen_display;
#endif

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

@@ -1,7 +1,7 @@ #ifndef STAMEN_H #define STAMEN_H
#include "stamenc.h"
#include "shared.h"
#include <exception> #include <format>

@@ -16,15 +16,17 @@ namespace stamen { class Menu {
struct private_ctor_t {};
public: friend class Generator;
typedef int (*callback_f)(void);
typedef stamen_callback_f callback_f;
typedef stamen_display_f display_f;
Menu(const Menu &) = delete; Menu &operator=(const Menu &) = delete;
struct private_ctor_t {};
// Tag type dispatch Menu(private_ctor_t, const std::string &code, const std::string &prompt) : Menu(code, prompt) {}

@@ -32,14 +34,10 @@ public: Menu(private_ctor_t, const std::string &code, const callback_f callback) : Menu(code, callback) {}
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 print(const std::string &entry) { internal_print(entry, 1); }
static void insert(const std::string &code, const callback_f callback);
static void print(const std::string &entry) { print(entry, 1); }
private: Menu(const std::string &code, const std::string &prompt) : code(code), title(prompt) {}

@@ -53,7 +51,7 @@ private: return lookup; }
static void print(const std::string &entry, const int depth);
static void internal_print(const std::string &entry, const int depth);
static const Menu *getMenu(const std::string &code) { static lookup_t &lookup = getLookup();

@@ -65,12 +63,7 @@ private: const std::string code, title; const callback_f callback = nullptr;
struct lookup_item_t {
lookup_item_t(const std::string &code, const std::string &prompt)
: code(code), prompt(prompt) {}
const std::string code, prompt;
};
typedef std::pair<std::string, std::string> lookup_item_t;
std::vector<lookup_item_t> items; };

@@ -102,23 +95,22 @@ inline void Menu::insert(const std::string &code, const callback_f callback) { std::forward_as_tuple(private_ctor_t{}, code, callback)); }
inline void Menu::print(const std::string &code, const int depth) {
inline void Menu::internal_print(const std::string &code, const int depth) {
const Menu *menu = getMenu(code); if (!menu) return; if (depth == 1) std::cout << std::format("{}({})\n", menu->title, code); if (!menu->callback) {
for (const auto &item : menu->items) {
for (const auto &[code, prompt] : menu->items) {
std::cout << std::format("{}{} ({})\n", std::string(depth << 1, ' '),
item.prompt, item.code);
menu->print(item.code, depth + 1);
prompt, code);
menu->internal_print(code, depth + 1);
} } }
int builtinDisplay(const std::string &title, const ::item_t items[],
std::size_t size);
int builtinDisplay(const char *title, const ::item_t items[], int size);
} // namespace stamen

diff --git a/ include/stamenc.h b/ include/stamenc.h

@@ -1,26 +1,17 @@ #ifndef CSTAMEN_H #define CSTAMEN_H
#include "shared.h"
#ifdef __cplusplus #define EXTERNC extern "C" #else #define EXTERNC extern #endif
typedef int (*callback_f)(void);
typedef struct item_t item_t;
struct item_t {
callback_f callback;
const char *prompt;
};
typedef int (*display_f)(const char *, const item_t[], int);
extern const display_f display;
EXTERNC void stamen_read(const char *file); EXTERNC void stamen_print(const char *entry);
EXTERNC void stamen_insert(const char *code, callback_f callback);
EXTERNC void stamen_insert(const char *code, stamen_callback_f callback);
EXTERNC int stamen_builtin_display(const char *title, const item_t items[], int size); #endif

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

@@ -28,26 +28,28 @@ public: } static void generateSource(std::ostream &os, bool cpp) {
os << std::format("#include <stamen{}.h>\n", !cpp ? "c" : "");
os << "#include <stamenc.h>\n";
os << "#include \"shared.h\"\n\n";
if (cpp) os << "namespace stamen {\n";
if (cpp) os << "namespace stamen {\n\n";
for (const auto &[code, _] : Menu::getLookup()) { const Menu *menu = Menu::getMenu(code); if (!menu) throw EGenerate(); if (menu->callback) continue; os << std::format("int {}(void) {{\n", menu->code);
os << std::format("\tstatic const item_t items[] = {{\n");
for (const auto &item : menu->items) {
os << std::format("\t\t{{ {}, \"{}\" }},\n", item.code, item.prompt);
for (const auto &[code, prompt] : menu->items) {
os << std::format("\t\t{{ {}, \"{}\" }},\n", code, prompt);
} os << std::format("\t}};\n");
os << std::format("\treturn {}display(\"{}\", items, "
os << std::format("\treturn stamen_display(\"{}\", items, "
"sizeof(items) / sizeof(item_t));\n",
cpp ? "Menu::" : "", menu->title);
menu->title);
os << std::format("}}\n\n"); }
if (cpp) os << "\n}\n";
if (cpp) os << "}\n";
} };

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

@@ -7,10 +7,9 @@ namespace stamen {
int builtinDisplay(const std::string &title, const ::item_t items[],
std::size_t size) {
int choice;
int builtinDisplay(const char *title, const ::item_t items[], int size) {
const int digits = std::log10(size) + 1;
int choice;
while (true) { std::cout << std::format("{}:\n", title);

diff --git a/ src/stamenc.cpp b/ src/stamenc.cpp

@@ -1,13 +1,11 @@
#include "../include/stamen.h"
#include "../include/stamenc.h"
#include "../include/stamen.h"
using namespace stamen;
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); }
void stamen_insert(const char *code, callback_f callback) {
void stamen_insert(const char *code, stamen_callback_f callback) {
Menu::insert(code, callback); }