First steps of implementing command-line processing in the ascii driver.
This commit is contained in:
@@ -16,6 +16,9 @@ static void if_error_print_and_exit(const std::string_view str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DPrints are currently not going through the readline device.
|
||||||
|
// doing so would not currently be thread-safe. Do I care about
|
||||||
|
// that? I'm not sure.
|
||||||
static void dprint_callback(const char *oneline, size_t size) {
|
static void dprint_callback(const char *oneline, size_t size) {
|
||||||
fwrite("**", 1, 2, stderr);
|
fwrite("**", 1, 2, stderr);
|
||||||
fwrite(oneline, 1, size, stderr);
|
fwrite(oneline, 1, size, stderr);
|
||||||
@@ -91,6 +94,7 @@ class Driver {
|
|||||||
std::unique_ptr<struct pollfd[]> pollvec_;
|
std::unique_ptr<struct pollfd[]> pollvec_;
|
||||||
std::unique_ptr<char[]> chbuf_;
|
std::unique_ptr<char[]> chbuf_;
|
||||||
ReadlineDevice readline_device_;
|
ReadlineDevice readline_device_;
|
||||||
|
std::string console_command_;
|
||||||
|
|
||||||
sslutil::UniqueCTX ssl_server_ctx_;
|
sslutil::UniqueCTX ssl_server_ctx_;
|
||||||
sslutil::UniqueCTX ssl_client_secure_ctx_;
|
sslutil::UniqueCTX ssl_client_secure_ctx_;
|
||||||
@@ -197,34 +201,58 @@ class Driver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_console_output() {
|
void channel_printbuffer() {
|
||||||
if (engw.get_have_prints(&engw)) {
|
if (engw.get_have_prints(&engw)) {
|
||||||
uint32_t ndata;
|
uint32_t ndata;
|
||||||
const char *data;
|
const char *data;
|
||||||
engw.play_access(&engw, AccessKind::CHANNEL_PRINTS, 0, 0, "", &ndata, &data);
|
engw.play_access(&engw, AccessKind::CHANNEL_PRINTS, 0, 0, "", &ndata, &data);
|
||||||
if (ndata > 0) {
|
if (ndata > 0) {
|
||||||
if (ndata > DRV_SHORTSTRING_SIZE) ndata = DRV_SHORTSTRING_SIZE;
|
if (ndata > DRV_SHORTSTRING_SIZE) ndata = DRV_SHORTSTRING_SIZE;
|
||||||
std::string_view src(data, ndata);
|
readline_device_.printline(std::string_view(data, ndata));
|
||||||
int consumed;
|
|
||||||
std::u32string cps = drvutil::utf8_to_utf32(src, &consumed);
|
|
||||||
readline_device_.print(cps);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_console_command(std::string_view addition)
|
||||||
|
{
|
||||||
|
std::string cmd = console_command_ + std::string(addition);
|
||||||
|
console_command_.clear();
|
||||||
|
uint32_t ndata;
|
||||||
|
const char *data;
|
||||||
|
engw.play_access(&engw, AccessKind::VALIDATE_LUA_EXPR,
|
||||||
|
0, cmd.size(), cmd.c_str(), &ndata, &data);
|
||||||
|
std::string_view message(data, ndata);
|
||||||
|
|
||||||
|
// Handle the command.
|
||||||
|
if (message == "truncated lua") {
|
||||||
|
console_command_ = cmd;
|
||||||
|
} else if (message == "white space") {
|
||||||
|
readline_device_.printline("white space.");
|
||||||
|
} else if (message == "slash command") {
|
||||||
|
readline_device_.printline("slash command.");
|
||||||
|
} else if (message.empty()) {
|
||||||
|
readline_device_.printline("valid lua");
|
||||||
|
} else {
|
||||||
|
readline_device_.printline(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (console_command_.empty()) {
|
||||||
|
readline_device_.set_prompt(">");
|
||||||
|
} else {
|
||||||
|
readline_device_.set_prompt(">>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handle_console_input() {
|
void handle_console_input() {
|
||||||
read_console_recently_ = false;
|
read_console_recently_ = false;
|
||||||
std::u32string prompt = drvutil::utf8_to_utf32(">", nullptr);
|
|
||||||
readline_device_.set_prompt(prompt);
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::u32string cps = console_read();
|
std::u32string cps = console_read();
|
||||||
if (cps.size() == 0) break;
|
if (cps.size() == 0) break;
|
||||||
read_console_recently_ = true;
|
read_console_recently_ = true;
|
||||||
for (char32_t c : cps) {
|
for (char32_t c : cps) {
|
||||||
std::u32string line = readline_device_.putcode(c);
|
std::string line = readline_device_.putcode(c);
|
||||||
if (!line.empty()) {
|
if (!line.empty()) {
|
||||||
std::string utf8 = drvutil::utf32_to_utf8(line);
|
add_console_command(line);
|
||||||
engw.play_recv_incoming(&engw, 0, utf8.size(), utf8.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -588,6 +616,8 @@ class Driver {
|
|||||||
int drive(int argc, char *argv[]) {
|
int drive(int argc, char *argv[]) {
|
||||||
// Set up the console readline device.
|
// Set up the console readline device.
|
||||||
readline_device_.set_print_callback(console_write);
|
readline_device_.set_print_callback(console_write);
|
||||||
|
readline_device_.set_prompt(">");
|
||||||
|
console_command_.clear();
|
||||||
|
|
||||||
// Remove the program name from argv.
|
// Remove the program name from argv.
|
||||||
std::string program = argv[0];
|
std::string program = argv[0];
|
||||||
@@ -659,12 +689,11 @@ class Driver {
|
|||||||
// Main loop.
|
// Main loop.
|
||||||
while (!engw.get_stop_driver(&engw)) {
|
while (!engw.get_stop_driver(&engw)) {
|
||||||
handle_lua_source();
|
handle_lua_source();
|
||||||
handle_console_output();
|
|
||||||
handle_new_outgoing_sockets();
|
handle_new_outgoing_sockets();
|
||||||
handle_socket_input_output();
|
handle_socket_input_output();
|
||||||
handle_console_input();
|
handle_console_input();
|
||||||
engw.play_update(&engw, drvutil::get_monotonic_clock());
|
engw.play_update(&engw, drvutil::get_monotonic_clock());
|
||||||
handle_console_output();
|
channel_printbuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#define MAXLINE 512
|
#define MAXLINE 512
|
||||||
|
|
||||||
|
|
||||||
|
static std::u32string white_(1, ' ');
|
||||||
|
static std::u32string newline_(1, '\n');
|
||||||
|
|
||||||
static std::u32string n_backspaces(int n) {
|
static std::u32string n_backspaces(int n) {
|
||||||
std::u32string result(3 * n, 0);
|
std::u32string result(3 * n, 0);
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
@@ -24,8 +28,8 @@ void ReadlineDevice::set_print_callback(print_callback cb) {
|
|||||||
print_cb_ = cb;
|
print_cb_ = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadlineDevice::set_prompt(const std::u32string &prompt) {
|
void ReadlineDevice::set_prompt(std::string_view prompt) {
|
||||||
desired_prompt_ = prompt;
|
desired_prompt_ = drvutil::utf8_to_utf32(prompt, nullptr);
|
||||||
echo_command();
|
echo_command();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,46 +70,46 @@ void ReadlineDevice::echo_command() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u32string ReadlineDevice::putcode(char32_t c) {
|
std::string ReadlineDevice::putcode(char32_t c) {
|
||||||
if ((c == '\n') && (readline_lastc_ == '\r')) {
|
if ((c == '\n') && (readline_lastc_ == '\r')) {
|
||||||
// Ignore newline immediately after carriage return.
|
// Ignore newline immediately after carriage return.
|
||||||
// Otherwise, crlf produces two newlines.
|
// Otherwise, crlf produces two newlines.
|
||||||
return std::u32string();
|
return "";
|
||||||
} else if ((c == '\r') || (c == '\n')) {
|
} else if ((c == '\r') || (c == '\n')) {
|
||||||
std::u32string white(1, ' ');
|
|
||||||
std::u32string newline(1, '\n');
|
|
||||||
echo_command();
|
echo_command();
|
||||||
print_cb_(white + newline);
|
print_cb_(white_ + newline_);
|
||||||
std::u32string result = desired_command_ + newline;
|
std::u32string result = desired_command_ + newline_;
|
||||||
desired_command_.clear();
|
desired_command_.clear();
|
||||||
current_prompt_.clear();
|
current_prompt_.clear();
|
||||||
current_command_.clear();
|
current_command_.clear();
|
||||||
echo_command();
|
echo_command();
|
||||||
return result;
|
return drvutil::utf32_to_utf8(result);
|
||||||
} else if ((c == '\b') || (c == 127)) {
|
} else if ((c == '\b') || (c == 127)) {
|
||||||
int len = desired_command_.size();
|
int len = desired_command_.size();
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
desired_command_ = desired_command_.substr(0, len-1);
|
desired_command_ = desired_command_.substr(0, len-1);
|
||||||
}
|
}
|
||||||
echo_command();
|
echo_command();
|
||||||
return std::u32string();
|
return "";
|
||||||
} else if ((c >= 32)&&(c <= 0x10FFFF)) {
|
} else if ((c >= 32)&&(c <= 0x10FFFF)) {
|
||||||
int len = desired_command_.size();
|
int len = desired_command_.size();
|
||||||
if (len < MAXLINE) {
|
if (len < MAXLINE) {
|
||||||
desired_command_ = desired_command_ + c;
|
desired_command_ = desired_command_ + c;
|
||||||
}
|
}
|
||||||
echo_command();
|
echo_command();
|
||||||
return std::u32string();
|
return "";
|
||||||
}
|
}
|
||||||
readline_lastc_ = c;
|
readline_lastc_ = c;
|
||||||
return std::u32string();
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadlineDevice::print(const std::u32string &s) {
|
|
||||||
if (!s.empty()) {
|
void ReadlineDevice::printline(std::string_view s) {
|
||||||
|
bool missing_newline = ((s.size() == 0) || (s[s.size() - 1] != '\n'));
|
||||||
|
std::u32string utf32 = drvutil::utf8_to_utf32(s, nullptr);
|
||||||
erase_command();
|
erase_command();
|
||||||
print_cb_(s);
|
print_cb_(utf32);
|
||||||
|
if (missing_newline) print_cb_(newline_);
|
||||||
echo_command();
|
echo_command();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,15 +28,19 @@ public:
|
|||||||
void set_print_callback(print_callback cb);
|
void set_print_callback(print_callback cb);
|
||||||
|
|
||||||
// change the prompt.
|
// change the prompt.
|
||||||
void set_prompt(const std::u32string &prompt);
|
void set_prompt(std::string_view prompt);
|
||||||
|
|
||||||
// Use this to print anything on the console.
|
// Use this to print anything on the console.
|
||||||
void print(const std::u32string &cps);
|
//
|
||||||
|
// if the string doesn't end in a newline, one will
|
||||||
|
// be automatically added.
|
||||||
|
//
|
||||||
|
void printline(std::string_view cps);
|
||||||
|
|
||||||
// Whenever the user types a character, call 'putcode'. If the code is
|
// Whenever the user types a character, call 'putcode'. If the code is
|
||||||
// newline, this returns the line of text that was entered, including the
|
// newline, this returns the line of text that was entered, including the
|
||||||
// newline. Otherwise returns empty string. Backspace is handled here.
|
// newline. Otherwise returns empty string. Backspace is handled here.
|
||||||
std::u32string putcode(char32_t codepoint);
|
std::string putcode(char32_t codepoint);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user