stamenStatic Menu Generator |
git clone git://git.dimitrijedobrota.com/stamen.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
menu.cpp (2669B)
1 #include <deque> 2 #include <fstream> 3 #include <iostream> 4 #include <sstream> 5 #include <tuple> 6 #include <unordered_set> 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::unordered_set<std::string> refd; 23 std::fstream fst(filename); 24 std::string line; 25 std::string delim; 26 std::string code; 27 std::string prompt; 28 29 auto last = menu_lookup.end(); 30 while (std::getline(fst, line)) 31 { 32 if (line.empty()) continue; 33 34 std::istringstream iss(line); 35 iss >> delim >> code >> std::ws; 36 std::getline(iss, prompt); 37 38 if (delim != "+") 39 { 40 last->second.insert(code, prompt); 41 refd.insert(code); 42 } 43 else 44 { 45 const auto [iter, succ] = menu_lookup.emplace( 46 std::piecewise_construct, 47 std::forward_as_tuple(code), 48 std::forward_as_tuple(menu_t::private_ctor_t {}, code, prompt)); 49 last = iter; 50 } 51 } 52 53 for (const auto& ref : refd) 54 { 55 if (!menu_lookup.contains(ref)) 56 { 57 free_lookup.emplace(ref, nullptr); 58 } 59 } 60 } 61 62 void insert(const char* code, callback_f callback) 63 { 64 auto itr = free_lookup.find(code); 65 if (itr == free_lookup.end()) 66 { 67 std::cout << "Stamen: unknown callback registration...\n" << std::flush; 68 return; 69 } 70 free_lookup.emplace(code, callback); 71 } 72 73 int dynamic(const char* code, display_f disp) 74 { 75 menu::display_stub_default = code; 76 menu::display = disp; 77 return display_stub(0); 78 } 79 80 int display_stub(std::size_t idx) 81 { 82 static std::deque<const menu_t*> stack; 83 84 const std::string& code = 85 !stack.empty() ? stack.back()->get_code(idx) : display_stub_default; 86 87 const auto ml_it = menu_lookup.find(code); 88 if (ml_it != menu_lookup.end()) 89 { 90 const auto& m = ml_it->second; // NOLINT 91 92 stack.push_back(&m); 93 const int ret = 94 display(m.get_title().c_str(), m.get_itemv(), m.get_size()); 95 stack.pop_back(); 96 97 return ret; 98 } 99 100 const auto fl_it = free_lookup.find(code); 101 if (fl_it != free_lookup.end()) return fl_it->second(0); 102 103 std::cout << "Stamen: nothing to do...\n" << std::flush; 104 return 1; 105 } 106 107 void menu_t::insert(const std::string& code, 108 const std::string& prompt, 109 callback_f callback) 110 { 111 char* buffer = new char[prompt.size() + 1]; // NOLINT 112 strcpy(buffer, prompt.c_str()); // NOLINT 113 114 m_items.emplace_back(callback, buffer); 115 m_codes.emplace_back(code, prompt); 116 } 117 118 } // namespace stamen::menu