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>
7 #include "stamen/stamen.hpp"
9 namespace {
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 }
21 } // namespace
23 namespace stamen {
25 Stamen::Stamen(std::istream& ist)
26 {
27 using namespace std::placeholders; // NOLINT
29 std::unordered_set<std::string> refd;
30 std::string line;
31 std::string delim;
32 std::string code;
33 std::string prompt;
35 auto last = m_menu_lookup.end();
36 while (std::getline(ist, line))
37 {
38 if (line.empty()) continue;
40 std::istringstream iss(line);
41 iss >> delim >> code >> std::ws;
42 std::getline(iss, prompt);
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 }
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 }
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 }
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 }
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;
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();
100 return ret;
101 }
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 }
109 warning("no callback for", code);
111 return 1;
112 }
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 }
121 } // namespace stamen