add a poll based EventManager and use it for ncurse client update
This commit is contained in:
parent
d5dc5dff7f
commit
ab47b72dc8
45
src/event_manager.cc
Normal file
45
src/event_manager.cc
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
src/event_manager.hh
Normal file
29
src/event_manager.hh
Normal file
|
@ -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
|
||||
|
55
src/main.cc
55
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user