134 lines
3.2 KiB
C++
134 lines
3.2 KiB
C++
//
|
|
// ncurses-poll.hpp
|
|
//
|
|
// A header for performing asynchronous I/O with ncurses using Boost.Asio.
|
|
//
|
|
// @author CismonX <admin@cismon.net>
|
|
//
|
|
|
|
#ifndef NCURSES_POLL_HPP_
|
|
#define NCURSES_POLL_HPP_
|
|
|
|
#include <boost/asio.hpp>
|
|
#include <boost/bind.hpp>
|
|
#include <curses.h>
|
|
|
|
template <typename Session>
|
|
class ncurses_poll {
|
|
|
|
using stream_descriptor_t = boost::asio::posix::stream_descriptor;
|
|
|
|
/// Provides asynchronous I/O functionalities for this ncurses instance.
|
|
stream_descriptor_t sd_;
|
|
|
|
/// I/O context used by the stream descriptor.
|
|
boost::asio::io_context *context_;
|
|
|
|
/// File pointer of this tty.
|
|
FILE *file_ = nullptr;
|
|
|
|
/// Screen pointer of this ncurses instance.
|
|
SCREEN *screen_ = nullptr;
|
|
|
|
/// User-defined session for this ncurses instance.
|
|
Session session_;
|
|
|
|
public:
|
|
/// Provides support for stackless coroutines.
|
|
boost::asio::coroutine coro;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param io_context The I/O context used for dispatching handlers.
|
|
*/
|
|
explicit ncurses_poll(boost::asio::io_context& io_context) :
|
|
sd_(io_context), context_(&io_context), session_(this) {}
|
|
|
|
/**
|
|
* Deleted default constructor.
|
|
*/
|
|
ncurses_poll() = delete;
|
|
|
|
/**
|
|
* Initialize ncurses instance.
|
|
*
|
|
* @param path File path. e.g. "/dev/pts/0". Empty for current tty.
|
|
*/
|
|
int init(const std::string& path = ttyname(STDIN_FILENO)) {
|
|
file_ = fopen(path.c_str(), "r+");
|
|
if (file_ == nullptr) {
|
|
return errno;
|
|
}
|
|
screen_ = newterm(nullptr, file_, file_);
|
|
boost::system::error_code ec;
|
|
sd_.assign(fileno(file_), ec);
|
|
return ec.value();
|
|
}
|
|
|
|
/**
|
|
* Invoke the given callback once the terminal is readable.
|
|
*
|
|
* @param read_cb The callback to be invoked.
|
|
*/
|
|
template <typename F>
|
|
void on_readable(F&& read_cb) {
|
|
sd_.async_wait(stream_descriptor_t::wait_read, boost::bind<void>(
|
|
[this, read_cb](const boost::system::error_code& ec) {
|
|
set_term(screen_);
|
|
read_cb(ec, this);
|
|
}, boost::asio::placeholders::error));
|
|
}
|
|
|
|
/**
|
|
* Invoke the given callback once the terminal is writable.
|
|
*
|
|
* @param write_cb The callback to be invoked.
|
|
*/
|
|
template <typename F>
|
|
void on_writable(F&& write_cb) {
|
|
sd_.async_wait(stream_descriptor_t::wait_write, boost::bind<void>(
|
|
[this, write_cb](const boost::system::error_code& ec) {
|
|
set_term(screen_);
|
|
write_cb(ec, this);
|
|
}, boost::asio::placeholders::error));
|
|
}
|
|
|
|
/**
|
|
* Get current session.
|
|
*/
|
|
Session *session() {
|
|
return &session_;
|
|
}
|
|
|
|
/**
|
|
* Get screen pointer of this ncurses instance.
|
|
*/
|
|
SCREEN *screen() const {
|
|
return screen_;
|
|
}
|
|
|
|
/**
|
|
* Get current I/O context.
|
|
*/
|
|
boost::asio::io_context *get_io_context() {
|
|
return context_;
|
|
}
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
~ncurses_poll() {
|
|
if (screen_) {
|
|
set_term(screen_);
|
|
endwin();
|
|
delscreen(screen_);
|
|
}
|
|
if (file_) {
|
|
fclose(file_);
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif
|