stamen

Stamen - static menu generator
git clone git://git.dimitrijedobrota.com/stamen.git
Log | Files | Refs | README | LICENSE

menu.cpp (2281B)


      1 #include <deque>
      2 #include <format>
      3 #include <fstream>
      4 #include <iostream>
      5 #include <sstream>
      6 #include <tuple>
      7 #include <utility>
      8 
      9 #include "stamen/menu.hpp"
     10 
     11 namespace stamen::menu {
     12 
     13 // NOLINTBEGIN
     14 std::unordered_map<std::string, menu_t> menu_lookup;
     15 std::unordered_map<std::string, callback_f> free_lookup;
     16 std::string display_stub_default;
     17 display_f display;
     18 // NOLINTEND
     19 
     20 void read(const char* filename)
     21 {
     22   std::fstream fst(filename);
     23   std::string line;
     24   std::string delim;
     25   std::string code;
     26   std::string prompt;
     27 
     28   auto last = menu_lookup.end();
     29   while (std::getline(fst, line))
     30   {
     31     if (line.empty()) continue;
     32 
     33     std::istringstream iss(line);
     34     iss >> delim >> code >> std::ws;
     35     std::getline(iss, prompt);
     36 
     37     if (delim != "+") last->second.insert(code, prompt);
     38     else
     39     {
     40       const auto [iter, succ] = menu_lookup.emplace(
     41           std::piecewise_construct,
     42           std::forward_as_tuple(code),
     43           std::forward_as_tuple(menu_t::private_ctor_t {}, code, prompt));
     44       last = iter;
     45     }
     46   }
     47 }
     48 
     49 void insert(const char* code, callback_f callback)
     50 {
     51   free_lookup.emplace(code, callback);
     52 }
     53 
     54 int dynamic(const char* code, display_f disp)
     55 {
     56   menu::display_stub_default = code;
     57   menu::display              = disp;
     58   return display_stub(0);
     59 }
     60 
     61 int display_stub(std::size_t idx)
     62 {
     63   static std::deque<const menu_t*> stack;
     64 
     65   const std::string& code =
     66       !stack.empty() ? stack.back()->get_code(idx) : display_stub_default;
     67 
     68   const auto ml_it = menu_lookup.find(code);
     69   if (ml_it != menu_lookup.end())
     70   {
     71     const auto& m = ml_it->second;  // NOLINT
     72 
     73     stack.push_back(&m);
     74     const int ret =
     75         display(m.get_title().c_str(), m.get_itemv(), m.get_size());
     76     stack.pop_back();
     77 
     78     return ret;
     79   }
     80 
     81   const auto fl_it = free_lookup.find(code);
     82   if (fl_it != free_lookup.end()) return fl_it->second(0);
     83 
     84   std::cout << "Stamen: nothing to do..." << std::endl;
     85   return 1;
     86 }
     87 
     88 void menu_t::insert(const std::string& code,
     89                     const std::string& prompt,
     90                     callback_f callback)
     91 {
     92   char* buffer = new char[prompt.size() + 1];  // NOLINT
     93   strcpy(buffer, prompt.c_str());  // NOLINT
     94 
     95   m_items.emplace_back(callback, buffer);
     96   m_codes.emplace_back(code, prompt);
     97 }
     98 
     99 }  // namespace stamen::menu