stamenStatic Menu Generator |
git clone git://git.dimitrijedobrota.com/stamen.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
stamen.cpp (2524B)
0 #include <cstddef> 1 #include <iostream> 2 #include <sstream> 3 #include <string> 4 #include <unordered_set> 5 #include <utility> 6 7 #include "stamen/stamen.hpp" 8 9 namespace { 10 11 void warning(const std::string& message, const std::string& addition) 12 { 13 std::cerr << "Stamen: " << message; 14 if (!addition.empty()) 15 { 16 std::cerr << ": " + addition; 17 } 18 std::cerr << '\n' << std::flush; 19 } 20 21 } // namespace 22 23 namespace stamen { 24 25 Stamen::Stamen(std::istream& ist) 26 { 27 using namespace std::placeholders; // NOLINT 28 29 std::unordered_set<std::string> refd; 30 std::string line; 31 std::string delim; 32 std::string code; 33 std::string prompt; 34 35 auto last = m_menu_lookup.end(); 36 while (std::getline(ist, line)) 37 { 38 if (line.empty()) continue; 39 40 std::istringstream iss(line); 41 iss >> delim >> code >> std::ws; 42 std::getline(iss, prompt); 43 44 if (delim != "+") 45 { 46 last->second.insert(code, 47 prompt, 48 [&](std::size_t idx) 49 { return this->display_stub(idx); }); 50 refd.insert(code); 51 } 52 else 53 { 54 const auto [iter, succ] = 55 m_menu_lookup.emplace(code, Menu(code, prompt)); 56 last = iter; 57 } 58 } 59 60 for (const auto& ref : refd) 61 { 62 if (!m_menu_lookup.contains(ref)) 63 { 64 m_free_lookup.emplace(ref, nullptr); 65 } 66 } 67 } 68 69 void Stamen::insert(const std::string& code, const callback_f& callback) 70 { 71 auto itr = m_free_lookup.find(code); 72 if (itr == m_free_lookup.end()) 73 { 74 warning("unknown callback registration", code); 75 return; 76 } 77 itr->second = callback; 78 } 79 80 int Stamen::dynamic(const std::string& code, const display_f& disp) 81 { 82 m_stub_default = code; 83 m_stub_display = disp; 84 return display_stub(0); 85 } 86 87 int Stamen::display_stub(std::size_t idx) 88 { 89 const std::string& code = !m_stub_stack.empty() 90 ? m_stub_stack.top()->item(idx).code 91 : m_stub_default; 92 93 const auto mit = m_menu_lookup.find(code); 94 if (mit != m_menu_lookup.end()) 95 { 96 m_stub_stack.push(&mit->second); 97 const int ret = m_stub_display(mit->second); 98 m_stub_stack.pop(); 99 100 return ret; 101 } 102 103 const auto fit = m_free_lookup.find(code); 104 if (fit != m_free_lookup.end() && fit->second != nullptr) 105 { 106 return fit->second(0); 107 } 108 109 warning("no callback for", code); 110 111 return 1; 112 } 113 114 void Menu::insert(const std::string& code, 115 const std::string& prompt, 116 const callback_f& callback) 117 { 118 m_items.emplace_back(code, prompt, callback); 119 } 120 121 } // namespace stamen