stamenStatic Menu Generator |
git clone git://git.dimitrijedobrota.com/stamen.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
generate.cpp (3681B)
0 #include <filesystem>
1 #include <fstream>
2 #include <iostream>
3 #include <string>
5 #include <cemplate/cemplate.hpp>
6 #include <poafloc/poafloc.hpp>
8 #include "stamen/stamen.hpp"
10 struct arguments_t
11 {
12 std::filesystem::path config;
13 std::string nspace = "stamen";
14 };
16 namespace {
18 void generate_include(std::ostream& ost,
19 const stamen::Stamen& inst,
20 const arguments_t& args)
21 {
22 using namespace std::string_literals; // NOLINT
23 using namespace cemplate; // NOLINT
25 Program prog(ost);
27 const auto func_f = [&prog](const auto& pair)
28 {
29 prog.function_decl(
30 pair.first, "int", {{{"std::size_t"s, "/* unused */"s}}});
31 };
33 prog.pragma("once")
34 .line_empty()
35 .include("cstddef")
36 .include("functional")
37 .include("string")
38 .include("vector")
39 .line_empty()
40 .namespace_open(args.nspace)
41 .value(R"(
42 struct menu_t
43 {
44 using callback_f = std::function<int(std::size_t)>;
46 static int visit(const menu_t& menu);
48 struct item_t
49 {
50 std::string prompt;
51 callback_f callback;
52 };
54 std::string title;
55 callback_f callback;
56 std::vector<item_t> items;
57 };
59 )");
61 prog.comment("generated function");
62 std::for_each(
63 std::begin(inst.menu_lookup()), std::end(inst.menu_lookup()), func_f);
64 prog.line_empty();
66 prog.comment("free function");
67 std::for_each(
68 std::begin(inst.free_lookup()), std::end(inst.free_lookup()), func_f);
70 prog.namespace_close(args.nspace);
71 }
73 void generate_source(std::ostream& ost,
74 const stamen::Stamen& inst,
75 const arguments_t& args,
76 const std::string& include_name)
77 {
78 using namespace std::string_literals; // NOLINT
79 using namespace cemplate; // NOLINT
81 const auto init_f = [](const auto& menu)
82 {
83 return InitlistNode({
84 string(menu.title()),
85 menu.code(),
86 InitlistNode(std::begin(menu.items()),
87 std::end(menu.items()),
88 [](const auto& item) -> InitlistNode
89 {
90 return {
91 string(item.prompt),
92 item.code,
93 };
94 }),
95 });
96 };
98 Program prog(ost);
100 prog.include("cstddef")
101 .line_empty()
102 .includeL(include_name)
103 .line_empty()
104 .namespace_open(args.nspace);
106 for (const auto& [_, menu] : inst.menu_lookup())
107 {
108 prog.function_open(
109 menu.code(), "extern int", {{{"std::size_t"s, "/* unused */"s}}})
110 .declaration("static const menu_t", "menu", init_f(menu))
111 .ret("menu_t::visit(menu)")
112 .function_close(menu.code());
113 }
115 prog.namespace_close(args.nspace);
116 }
118 } // namespace
120 int main(int argc, const char* argv[])
121 {
122 using namespace poafloc; // NOLINT
124 arguments_t args;
126 auto program = parser<arguments_t> {
127 positional {
128 argument {
129 "config",
130 &arguments_t::config,
131 },
132 },
133 group {
134 "Configuration options",
135 direct {
136 "n namespace",
137 &arguments_t::nspace,
138 "NAME output namespace",
139 },
140 },
141 };
143 program(args, argc, argv);
145 std::ifstream ifs(args.config);
146 const stamen::Stamen inst(ifs);
148 const auto include_filename = args.config.stem().replace_extension(".hpp");
149 std::ofstream include(include_filename);
150 generate_include(include, inst, args);
152 const auto source_filename = args.config.stem().replace_extension(".cpp");
153 std::ofstream source(source_filename);
154 generate_source(source, inst, args, include_filename);
156 return 0;
157 }