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