From ab47b72dc84e49d9b7e647b08af93020fa510616 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 28 Aug 2012 22:32:15 +0200 Subject: [PATCH] add a poll based EventManager and use it for ncurse client update --- src/event_manager.cc | 45 ++++++++++++++++++++++++++++++++++++ src/event_manager.hh | 29 +++++++++++++++++++++++ src/main.cc | 55 +++++++++++++++++++++++++------------------- 3 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 src/event_manager.cc create mode 100644 src/event_manager.hh 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 + +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 + +#include "utils.hh" + +namespace Kakoune +{ + +using EventHandler = std::function; + +class EventManager : public Singleton +{ +public: + void watch(int fd, EventHandler handler); + void unwatch(int fd); + + void handle_next_events(); + +private: + std::vector m_events; + std::vector 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> 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) {