stamenStatic Menu Generator | 
          
| git clone git://git.dimitrijedobrota.com/stamen.git | 
| Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | 
| commit | 327abb09023582d7a9310440fd011cf012ae4195 | 
| parent | 12c5ce88ce059481256dc028f9c672c1861655ca | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Thu, 13 Jun 2024 23:15:43 +0200 | 
Option to include system or user stamen header
| M | demo/CMakeLists.txt | | | ++ -- | 
| M | include/menu.h | | | +++++ ------ | 
| M | src/generate.cpp | | | ++++++++++++++++++++++++++++++++++++++++++ ---------------------------------------- | 
3 files changed, 58 insertions(+), 56 deletions(-)
diff --git a/ demo/CMakeLists.txt b/ demo/CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          configure_file(demo_menu.conf ${GENERATE_OUT}/demo_menu.conf COPYONLY)
        
        
          add_custom_command(
              OUTPUT ${GENERATE_OUT}/demo_menu.hpp ${GENERATE_OUT}/demo_menu.cpp
              COMMAND ${GENERATE_OUT}/stamen-generate --cpp ${GENERATE_OUT}/demo_menu.conf
              COMMAND ${GENERATE_OUT}/stamen-generate --user --cpp ${GENERATE_OUT}/demo_menu.conf
              DEPENDS demo_menu.conf stamen-generate
              COMMENT "Generating menu files"
          )
        
        
          @@ -23,7 +23,7 @@ 
          set_target_properties(demo PROPERTIES
        
        
          add_custom_command(
              OUTPUT ${GENERATE_OUT}/demo_menu.h ${GENERATE_OUT}/demo_menu.c
              COMMAND ${GENERATE_OUT}/stamen-generate --c ${GENERATE_OUT}/demo_menu.conf
              COMMAND ${GENERATE_OUT}/stamen-generate --user --c ${GENERATE_OUT}/demo_menu.conf
              DEPENDS demo_menu.conf stamen-generate
              COMMENT "Generating cmenu files"
          )
        
        diff --git a/ include/menu.h b/ include/menu.h
@@ -12,12 +12,6 @@
namespace stamen {
          class Menu {
              friend class Generator;
              static std::unordered_map<std::string, Menu> menu_lookup;
              static std::unordered_map<std::string, callback_f> free_lookup;
              static std::string display_stub_default;
              struct private_ctor_t {};
            public:
        
        
          @@ -59,6 +53,8 @@ 
          class Menu {
        
        
                  return entries.items[idx].callback;
              }
              static std::unordered_map<std::string, Menu> menu_lookup;
            private:
              Menu(std::string code, std::string prompt)
                  : code(std::move(code)), title(std::move(prompt)) {}
        
        
          @@ -93,6 +89,9 @@ 
          class Menu {
        
        
              const std::string code, title;
              Entries entries;
              static std::unordered_map<std::string, callback_f> free_lookup;
              static std::string display_stub_default;
          };
          } // namespace stamen
        
        diff --git a/ src/generate.cpp b/ src/generate.cpp
@@ -8,63 +8,65 @@
#include <iostream>
          #include <string>
          namespace stamen {
          const stamen_display_f stamen_display = stamen::builtin_display;
          class Generator {
            public:
              static void generateInclude(std::ostream &os, bool cpp) {
                  os << "#ifndef STAMEN_MENU_H\n";
                  os << "#define STAMEN_MENU_H\n\n";
          struct arguments_t {
              std::string config;
              bool cpp = false;
              bool user = false;
          } opt;
                  if (cpp) os << "#include \"stamen.hpp\"\n\n";
          void generateIncludeHeaders(std::ostream &os) {
              if (opt.user) {
                  if (opt.cpp) os << "#include \"stamen.hpp\"\n\n";
                  else os << "#include \"stamen.h\"\n\n";
              } else {
                  if (opt.cpp) os << "#include <stamen/stamen.hpp>\n\n";
                  else os << "#include <stamen/stamen.h>\n\n";
              }
          }
                  for (const auto &[code, menu] : Menu::menu_lookup) {
                      os << std::format("int {}(int);\n", menu.getCode());
                  }
          void generateInclude(std::ostream &os) {
              os << "#ifndef STAMEN_MENU_H\n";
              os << "#define STAMEN_MENU_H\n\n";
                  os << "\n#endif\n";
              }
              generateIncludeHeaders(os);
              static void generateSource(std::ostream &os, bool cpp) {
                  if (cpp) os << "#include \"stamen.hpp\"\n\n";
                  else os << "#include \"stamen.h\"\n\n";
              for (const auto &[code, menu] : stamen::Menu::menu_lookup) {
                  os << std::format("int {}(int);\n", menu.getCode());
              }
                  os << "#include \"shared.h\"\n\n";
                  for (const auto &[code, menu] : Menu::menu_lookup) {
                      os << std::format("int {}(int) {{\n", menu.getCode());
              os << "\n#endif\n";
          }
                      if (cpp) os << "\tstatic const stamen::item_t items[] = ";
                      else os << "\tstatic const stamen_item_t items[] = ";
          void generateSource(std::ostream &os) {
              os << "#include \"shared.h\"\n";
              generateIncludeHeaders(os);
                      os << "{\n";
                      for (int i = 0; i < menu.getSize(); i++) {
                          os << "\t\t{ " << menu.getCode(i);
                          os << ", \"" << menu.getPrompt(i) << "\" },\n";
                      }
                      os << "\t};\n";
              for (const auto &[code, menu] : stamen::Menu::menu_lookup) {
                  os << std::format("int {}(int) {{\n", menu.getCode());
                      if (cpp) os << "\treturn stamen::stamen_display";
                      else os << "\treturn stamen_display";
                  if (opt.cpp) os << "\tstatic const stamen::item_t items[] = ";
                  else os << "\tstatic const stamen_item_t items[] = ";
                      os << std::format("(\"{}\"", menu.getTitle());
                      os << ", items, sizeof(items) / sizeof(items[0]));\n";
                      os << "}\n\n";
                  os << "{\n";
                  for (int i = 0; i < menu.getSize(); i++) {
                      os << "\t\t{ " << menu.getCode(i);
                      os << ", \"" << menu.getPrompt(i) << "\" },\n";
                  }
              }
          };
          } // namespace stamen
                  os << "\t};\n";
          struct arguments_t {
              std::string config;
              bool cpp = false;
          };
                  if (opt.cpp) os << "\treturn stamen::stamen_display";
                  else os << "\treturn stamen_display";
                  os << std::format("(\"{}\"", menu.getTitle());
                  os << ", items, sizeof(items) / sizeof(items[0]));\n";
                  os << "}\n\n";
              }
          }
          int parse_opt(int key, const char *arg, args::Parser *parser) {
              auto arguments = (arguments_t *)parser->input();
              switch (key) {
              case 'u': arguments->user = true; break;
              case 666: arguments->cpp = false; break;
              case 777: arguments->cpp = true; break;
              case args::ARG:
        
        
          @@ -84,6 +86,8 @@ 
          static const args::option_t options[]{
        
        
              {0, 0, 0, 0, "Output mode", 1},
              {"c", 666, 0, 0, "Generate files for C"},
              {"cpp", 777, 0, 0, "Generate files for C++"},
              {0, 0, 0, 0, "Output settings", 2},
              {"user", 'u', 0, 0, "Include user stamen headers"},
              {0, 0, 0, 0, "Informational Options", -1},
              {0},
          };
        
        
          @@ -96,23 +100,22 @@ 
          static const args::argp_t argp{
        
        
          };
          int main(int argc, char *argv[]) {
              arguments_t arguments;
              if (args::parse(&argp, argc, argv, 0, &arguments)) {
              if (args::parse(&argp, argc, argv, 0, &opt)) {
                  std::cerr << "There was an error while parsing arguments";
                  return 0;
              }
              const auto &config = arguments.config;
              const auto &config = opt.config;
              stamen::Menu::read(config);
              std::string::size_type pos = arguments.config.rfind('.');
              std::string::size_type pos = opt.config.rfind('.');
              std::string base =
                  pos != std::string::npos ? config.substr(0, pos) : config;
              std::string ext = arguments.cpp ? "pp" : "";
              std::string ext = opt.cpp ? "pp" : "";
              std::ofstream source(base + ".c" + ext), include(base + ".h" + ext);
              stamen::Generator::generateSource(source, arguments.cpp);
              stamen::Generator::generateInclude(include, arguments.cpp);
              generateInclude(include);
              generateSource(source);
              return 0;
          }