summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-08-28 22:32:15 +0200
committerMaxime Coste <frrrwww@gmail.com>2012-08-28 22:32:15 +0200
commitab47b72dc84e49d9b7e647b08af93020fa510616 (patch)
tree0e86fd66a9bb27030dc140cd488f503f55206a5a
parentd5dc5dff7f5b971c4c9b8fe4eb3c272762964ffd (diff)
add a poll based EventManager and use it for ncurse client update
-rw-r--r--src/event_manager.cc45
-rw-r--r--src/event_manager.hh29
-rw-r--r--src/main.cc55
3 files changed, 105 insertions, 24 deletions
diff --git a/src/event_manager.cc b/src/event_manager.cc
new file mode 100644
index 00000000..2a8df29c
--- /dev/null
+++ b/src/event_manager.cc
@@ -0,0 +1,45 @@
+#include "event_manager.hh"
+
+#include <algorithm>
+
+namespace Kakoune
+{
+
+void EventManager::watch(int fd, EventHandler handler)
+{
+ auto event = std::find_if(m_events.begin(), m_events.end(),
+ [&](const pollfd& pfd) { return pfd.fd == fd; });
+ if (event != m_events.end())
+ throw runtime_error("fd already watched");
+
+ m_events.push_back(pollfd{ fd, POLLIN | POLLPRI, 0 });
+ m_handlers.push_back(std::move(handler));
+}
+
+void EventManager::unwatch(int fd)
+{
+ for (size_t i = 0; i < m_events.size(); ++i)
+ {
+ if (m_events[i].fd == fd)
+ {
+ m_events.erase(m_events.begin() + i);
+ m_handlers.erase(m_handlers.begin() + i);
+ return;
+ }
+ }
+}
+
+void EventManager::handle_next_events()
+{
+ int res = poll(m_events.data(), m_events.size(), -1);
+ if (res > 0)
+ {
+ for (size_t i = 0; i < m_events.size(); ++i)
+ {
+ if (m_events[i].revents & POLLIN)
+ m_handlers[i](m_events[i].fd);
+ }
+ }
+}
+
+}
diff --git a/src/event_manager.hh b/src/event_manager.hh
new file mode 100644
index 00000000..c1795983
--- /dev/null
+++ b/src/event_manager.hh
@@ -0,0 +1,29 @@
+#ifndef event_manager_hh_INCLUDED
+#define event_manager_hh_INCLUDED
+
+#include <poll.h>
+
+#include "utils.hh"
+
+namespace Kakoune
+{
+
+using EventHandler = std::function<void (int fd)>;
+
+class EventManager : public Singleton<EventManager>
+{
+public:
+ void watch(int fd, EventHandler handler);
+ void unwatch(int fd);
+
+ void handle_next_events();
+
+private:
+ std::vector<pollfd> m_events;
+ std::vector<EventHandler> m_handlers;
+};
+
+}
+
+#endif // event_manager_hh_INCLUDED
+
diff --git a/src/main.cc b/src/main.cc
index 53cddfac..ec18016e 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -14,6 +14,7 @@
#include "filter_registry.hh"
#include "hook_manager.hh"
#include "option_manager.hh"
+#include "event_manager.hh"
#include "context.hh"
#include "ncurses.hh"
#include "regex.hh"
@@ -442,6 +443,32 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
void run_unit_tests();
+void manage_next_keypress(Context& context)
+{
+ static int count = 0;
+ try
+ {
+ Key key = context.client().get_key();
+ if (key.modifiers == Key::Modifiers::None and isdigit(key.key))
+ count = count * 10 + key.key - '0';
+ else
+ {
+ auto it = keymap.find(key);
+ if (it != keymap.end())
+ {
+ context.numeric_param(count);
+ it->second(context);
+ context.draw_ifn();
+ }
+ count = 0;
+ }
+ }
+ catch (Kakoune::runtime_error& error)
+ {
+ context.print_status(error.description());
+ }
+}
+
int main(int argc, char* argv[])
{
GlobalOptionManager option_manager;
@@ -452,6 +479,7 @@ int main(int argc, char* argv[])
RegisterManager register_manager;
HighlighterRegistry highlighter_registry;
FilterRegistry filter_registry;
+ EventManager event_manager;
run_unit_tests();
@@ -507,32 +535,11 @@ int main(int argc, char* argv[])
context.change_editor(*buffer->get_or_create_window());
}
+ event_manager.watch(0, [&](int) { manage_next_keypress(context); });
+
context.draw_ifn();
- int count = 0;
while(not quit_requested)
- {
- try
- {
- Key key = context.client().get_key();
- if (key.modifiers == Key::Modifiers::None and isdigit(key.key))
- count = count * 10 + key.key - '0';
- else
- {
- auto it = keymap.find(key);
- if (it != keymap.end())
- {
- context.numeric_param(count);
- it->second(context);
- context.draw_ifn();
- }
- count = 0;
- }
- }
- catch (Kakoune::runtime_error& error)
- {
- context.print_status(error.description());
- }
- }
+ event_manager.handle_next_events();
}
catch (Kakoune::exception& error)
{