stamen

Static Menu Generator
git clone git://git.dimitrijedobrota.com/stamen.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |

stamen.cpp (2524B)


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